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

16 17 18 19 20

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

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

S
TD-1057  
Shengliang Guan 已提交
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
#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>
42
#else
S
TD-1057  
Shengliang Guan 已提交
43 44
  #include <regex.h>
  #include <stdio.h>
45
#endif
H
hzcheng 已提交
46

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

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

56 57
#define STMT_IFACE_ENABLED  1

58 59 60
#define REQ_EXTRA_BUF_LEN   1024
#define RESP_BUF_LEN        4096

S
slguan 已提交
61 62
extern char configDir[];

63 64 65 66
#define INSERT_JSON_NAME      "insert.json"
#define QUERY_JSON_NAME       "query.json"
#define SUBSCRIBE_JSON_NAME   "subscribe.json"

67 68
#define STR_INSERT_INTO     "INSERT INTO "

69 70 71 72 73 74
enum TEST_MODE {
    INSERT_TEST,            // 0
    QUERY_TEST,             // 1
    SUBSCRIBE_TEST,         // 2
    INVAID_TEST
};
75

76 77
#define MAX_RECORDS_PER_REQ     32766

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

80 81
#define MAX_SQL_SIZE       65536
#define BUFFER_SIZE        (65536*2)
82
#define COND_BUF_LEN       (BUFFER_SIZE - 30)
83 84 85
#define MAX_USERNAME_SIZE  64
#define MAX_PASSWORD_SIZE  64
#define MAX_HOSTNAME_SIZE  64
86
#define MAX_TB_NAME_SIZE   64
87
#define MAX_DATA_SIZE      (16*1024)+20     // max record len: 16*1024, timestamp string and ,('') need extra space
88 89 90 91
#define MAX_NUM_DATATYPE   10
#define OPT_ABORT          1 /* –abort */
#define STRING_LEN         60000
#define MAX_PREPARED_RAND  1000000
92
#define MAX_FILE_NAME_LEN  256              // max file name length on linux is 255.
93 94 95 96 97

#define   MAX_SAMPLES_ONCE_FROM_FILE   10000
#define   MAX_NUM_DATATYPE 10

#define   MAX_DB_COUNT           8
98
#define   MAX_SUPER_TABLE_COUNT  200
99 100 101
#define   MAX_COLUMN_COUNT       1024
#define   MAX_TAG_COUNT          128

102
#define   MAX_QUERY_SQL_COUNT    100
103
#define   MAX_QUERY_SQL_LENGTH   1024
104 105

#define   MAX_DATABASE_COUNT     256
106
#define INPUT_BUF_LEN   256
107

108
#define DEFAULT_TIMESTAMP_STEP  1
109

110

111 112 113 114 115
typedef enum CREATE_SUB_TALBE_MOD_EN {
  PRE_CREATE_SUBTBL,
  AUTO_CREATE_SUBTBL,
  NO_CREATE_SUBTBL
} CREATE_SUB_TALBE_MOD_EN;
116

117 118
typedef enum TALBE_EXISTS_EN {
  TBL_NO_EXISTS,
119
  TBL_ALREADY_EXISTS,
120 121 122
  TBL_EXISTS_BUTT
} TALBE_EXISTS_EN;

123
enum enumSYNC_MODE {
124 125
  SYNC_MODE,
  ASYNC_MODE,
126 127
  MODE_BUT
};
128

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

136 137 138 139 140 141
typedef enum enumQUERY_CLASS {
    SPECIFIED_CLASS,
    STABLE_CLASS,
    CLASS_BUT
} QUERY_CLASS;

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

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

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

189 190 191 192 193 194 195 196
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
};

H
hzcheng 已提交
197
/* Used by main to communicate with parse_opt. */
198 199
static char *g_dupstr = NULL;

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

typedef struct SColumn_S {
242 243
  char      field[TSDB_COL_NAME_LEN];
  char      dataType[16];
244
  uint32_t  dataLen;
245
  char      note[128];
246 247 248
} StrColumn;

typedef struct SSuperTable_S {
249 250 251
  char         sTblName[TSDB_TABLE_NAME_LEN];
  char         dataSource[MAX_TB_NAME_SIZE];  // rand_gen or sample
  char         childTblPrefix[TSDB_TABLE_NAME_LEN - 20]; // 20 characters reserved for seq
252 253
  char         insertMode[MAX_TB_NAME_SIZE];    // taosc, rest
  uint16_t     childTblExists;
254
  int64_t      childTblCount;
255 256
  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
257
  uint16_t     iface;                   // 0: taosc, 1: rest, 2: stmt
258
  int64_t      childTblLimit;
259
  uint64_t     childTblOffset;
260

261
//  int          multiThreadWriteOneTbl;  // 0: no, 1: yes
262
  uint32_t     interlaceRows;           //
263 264
  int          disorderRatio;           // 0: no disorder, >0: x%
  int          disorderRange;           // ms or us by database precision
265
  uint64_t     maxSqlLen;               //
266

267
  uint64_t     insertInterval;          // insert interval, will override global insert interval
268
  int64_t      insertRows;
269
  int64_t      timeStampStep;
270
  char         startTimestamp[MAX_TB_NAME_SIZE];
271
  char         sampleFormat[MAX_TB_NAME_SIZE];  // csv, json
272 273
  char         sampleFile[MAX_FILE_NAME_LEN];
  char         tagsFile[MAX_FILE_NAME_LEN];
274

275
  uint32_t     columnCount;
276
  StrColumn    columns[MAX_COLUMN_COUNT];
277
  uint32_t     tagCount;
278 279 280
  StrColumn    tags[MAX_TAG_COUNT];

  char*        childTblName;
281
  char*        colsOfCreateChildTable;
282 283
  uint64_t     lenOfOneRow;
  uint64_t     lenOfTagOfOneRow;
284 285 286 287 288

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

289
  uint32_t     tagSource;    // 0: rand, 1: tag sample
290
  char*        tagDataBuf;
291 292
  uint32_t     tagSampleCount;
  uint32_t     tagUsePos;
293

294
  // statistics
295 296
  uint64_t     totalInsertRows;
  uint64_t     totalAffectedRows;
297 298 299
} SSuperTable;

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

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

typedef struct SDataBase_S {
340
  char         dbName[TSDB_DB_NAME_LEN];
341
  bool         drop;  // 0: use exists, 1: if exists, drop then new create
342
  SDbCfg       dbCfg;
343
  uint64_t     superTblCount;
344 345 346 347
  SSuperTable  superTbls[MAX_SUPER_TABLE_COUNT];
} SDataBase;

typedef struct SDbs_S {
348
  char         cfgDir[MAX_FILE_NAME_LEN];
349
  char         host[MAX_HOSTNAME_SIZE];
350 351
  struct sockaddr_in serv_addr;

352
  uint16_t     port;
353 354
  char         user[MAX_USERNAME_SIZE];
  char         password[MAX_PASSWORD_SIZE];
355
  char         resultFile[MAX_FILE_NAME_LEN];
356 357 358
  bool         use_metric;
  bool         insert_only;
  bool         do_aggreFunc;
359
  bool         asyncMode;
360

361 362 363
  uint32_t     threadCount;
  uint32_t     threadCountByCreateTbl;
  uint32_t     dbCount;
364 365 366
  SDataBase    db[MAX_DB_COUNT];

  // statistics
367 368
  uint64_t     totalInsertRows;
  uint64_t     totalAffectedRows;
369

370 371
} SDbs;

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

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

410
  char*        childTblName;
411
  uint64_t     totalQueried;
412
} SuperQueryInfo;
413 414

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

424
  SpecifiedQueryInfo  specifiedQueryInfo;
425
  SuperQueryInfo      superQueryInfo;
426
  uint64_t     totalQueried;
427 428 429
} SQueryMetaInfo;

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

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

455
  // sample data
456
  int64_t   samplePos;
457
  // statistics
458 459
  uint64_t  totalInsertRows;
  uint64_t  totalAffectedRows;
460 461

  // insert delay statistics
462 463 464 465 466
  uint64_t  cntDelay;
  uint64_t  totalDelay;
  uint64_t  avgDelay;
  uint64_t  maxDelay;
  uint64_t  minDelay;
467

468
  // seq of query or subscribe
469
  uint64_t  querySeq;   // sequence number of sql command
470
  TAOS_SUB*  tsub;
471

472 473
} threadInfo;

474
#ifdef WINDOWS
475 476
#define _CRT_RAND_S

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

typedef unsigned __int32 uint32_t;

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

static HANDLE g_stdoutHandle;
static DWORD g_consoleMode;

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

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

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

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

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

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

538 539
#include <time.h>

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

545
#endif // ifdef Windows
546

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

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

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

565
SArguments g_args = {
566 567 568 569
                     NULL,            // metaFile
                     0,               // test_mode
                     "127.0.0.1",     // host
                     6030,            // port
S
Shuduo Sang 已提交
570
                     TAOSC_IFACE,     // iface
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 602
                     "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
603
                     (1024*1024),     // max_sql_len
604 605 606 607 608 609 610
                     10000,           // num_of_tables
                     10000,           // num_of_DPT
                     0,               // abort
                     0,               // disorderRatio
                     1000,            // disorderRange
                     1,               // method_of_delete
                     NULL             // arg_list
611 612 613 614 615
};



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

620 621 622 623
#if _MSC_VER <= 1900
#define __func__ __FUNCTION__
#endif

624
#define debugPrint(fmt, ...) \
625
    do { if (g_args.debug_print || g_args.verbose_print) \
626
      fprintf(stderr, "DEBG: "fmt, __VA_ARGS__); } while(0)
627

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

632 633 634 635
#define performancePrint(fmt, ...) \
    do { if (g_args.performance_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)

636 637 638 639
#define errorPrint(fmt, ...) \
    do { fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); } while(0)


640
///////////////////////////////////////////////////
H
hzcheng 已提交
641

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

644 645 646 647 648 649 650 651
#ifndef TAOSDEMO_COMMIT_SHA1
#define TAOSDEMO_COMMIT_SHA1 "unknown"
#endif

#ifndef TD_VERNUMBER
#define TD_VERNUMBER    "unknown"
#endif

652
#ifndef TAOSDEMO_STATUS
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
#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);
    }
}

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

743 744 745 746 747 748 749 750 751 752 753 754 755 756 757
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;
}

758
static void parse_args(int argc, char *argv[], SArguments *arguments) {
759 760 761 762 763

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

      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;
      }

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

1011
      arguments->disorderRatio = atoi(argv[++i]);
1012

1013
      if (arguments->disorderRatio > 50) {
1014
        arguments->disorderRatio = 50;
1015
      }
1016

1017
      if (arguments->disorderRatio < 0) {
1018
        arguments->disorderRatio = 0;
1019
      }
1020

1021
    } else if (strcmp(argv[i], "-R") == 0) {
1022 1023 1024 1025 1026 1027
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-R need a number following!\n");
        exit(EXIT_FAILURE);
      }
1028

1029
      arguments->disorderRange = atoi(argv[++i]);
1030 1031 1032
      if (arguments->disorderRange < 0)
        arguments->disorderRange = 1000;

1033
    } else if (strcmp(argv[i], "-a") == 0) {
1034 1035 1036 1037 1038 1039
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-a need a number following!\n");
        exit(EXIT_FAILURE);
      }
1040 1041 1042
      arguments->replica = atoi(argv[++i]);
      if (arguments->replica > 3 || arguments->replica < 1) {
          arguments->replica = 1;
1043
      }
1044 1045
    } else if (strcmp(argv[i], "-D") == 0) {
      arguments->method_of_delete = atoi(argv[++i]);
1046 1047 1048
      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 已提交
1049
      }
1050 1051 1052 1053
    } else if ((strcmp(argv[i], "--version") == 0) ||
        (strcmp(argv[i], "-V") == 0)){
      printVersion();
      exit(0);
1054 1055 1056 1057 1058
    } else if (strcmp(argv[i], "--help") == 0) {
      printHelp();
      exit(0);
    } else {
      printHelp();
1059
      errorPrint("%s", "ERROR: wrong options\n");
1060
      exit(EXIT_FAILURE);
S
TD-1057  
Shengliang Guan 已提交
1061 1062
    }
  }
1063

1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
  int columnCount;
  for (columnCount = 0; columnCount < MAX_NUM_DATATYPE; columnCount ++) {
    if (g_args.datatype[columnCount] == NULL) {
      break;
    }
  }

  if (0 == columnCount) {
    perror("data type error!");
    exit(-1);
  }
  g_args.num_of_CPR = columnCount;

1077
  if (((arguments->debug_print) && (arguments->metaFile == NULL))
1078
          || arguments->verbose_print) {
1079
    printf("###################################################################\n");
1080
    printf("# meta file:                         %s\n", arguments->metaFile);
1081
    printf("# Server IP:                         %s:%hu\n",
1082 1083
            arguments->host == NULL ? "localhost" : arguments->host,
            arguments->port );
1084 1085
    printf("# User:                              %s\n", arguments->user);
    printf("# Password:                          %s\n", arguments->password);
1086 1087
    printf("# Use metric:                        %s\n",
            arguments->use_metric ? "true" : "false");
1088
    if (*(arguments->datatype)) {
1089 1090 1091 1092 1093 1094 1095
        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");
1096
    }
1097
    printf("# Insertion interval:                %"PRIu64"\n",
1098
            arguments->insert_interval);
1099
    printf("# Number of records per req:         %u\n",
1100
            arguments->num_of_RPR);
1101
    printf("# Max SQL length:                    %"PRIu64"\n",
1102
            arguments->max_sql_len);
1103
    printf("# Length of Binary:                  %d\n", arguments->len_of_binary);
1104
    printf("# Number of Threads:                 %d\n", arguments->num_of_threads);
1105
    printf("# Number of Tables:                  %"PRId64"\n",
1106
            arguments->num_of_tables);
1107
    printf("# Number of Data per Table:          %"PRId64"\n",
1108
            arguments->num_of_DPT);
1109 1110 1111 1112 1113
    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);
1114

1115 1116 1117 1118
    }
    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);
1119
    printf("# Print verbose info:                %d\n", arguments->verbose_print);
1120
    printf("###################################################################\n");
1121 1122

    prompt();
1123
  }
1124
}
H
hzcheng 已提交
1125

1126 1127
static bool getInfoFromJsonFile(char* file);
static void init_rand_data();
1128
static void tmfclose(FILE *fp) {
1129 1130 1131 1132
  if (NULL != fp) {
    fclose(fp);
  }
}
1133

1134
static void tmfree(char *buf) {
1135 1136
  if (NULL != buf) {
    free(buf);
H
Hui Li 已提交
1137
  }
1138
}
H
Hui Li 已提交
1139

1140
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet) {
1141 1142 1143
  int i;
  TAOS_RES *res = NULL;
  int32_t   code = -1;
1144

S
Shuduo Sang 已提交
1145
  for (i = 0; i < 5 /* retry */; i++) {
1146 1147 1148
    if (NULL != res) {
      taos_free_result(res);
      res = NULL;
H
hzcheng 已提交
1149
    }
1150

1151 1152 1153 1154
    res = taos_query(taos, command);
    code = taos_errno(res);
    if (0 == code) {
      break;
1155
    }
H
hzcheng 已提交
1156 1157
  }

1158
  verbosePrint("%s() LN%d - command: %s\n", __func__, __LINE__, command);
1159
  if (code != 0) {
1160
    if (!quiet) {
1161 1162
      errorPrint("Failed to execute %s, reason: %s\n",
              command, taos_errstr(res));
1163
    }
1164 1165 1166
    taos_free_result(res);
    //taos_close(taos);
    return -1;
1167
  }
H
hzcheng 已提交
1168

1169 1170 1171 1172
  if (INSERT_TYPE == type) {
    int affectedRows = taos_affected_rows(res);
    taos_free_result(res);
    return affectedRows;
H
hzcheng 已提交
1173
  }
1174

1175
  taos_free_result(res);
1176 1177
  return 0;
}
H
hzcheng 已提交
1178

1179
static void appendResultBufToFile(char *resultBuf, threadInfo *pThreadInfo)
1180
{
1181 1182
  pThreadInfo->fp = fopen(pThreadInfo->filePath, "at");
  if (pThreadInfo->fp == NULL) {
1183 1184
      errorPrint(
              "%s() LN%d, failed to open result file: %s, result will not save to file\n",
1185
              __func__, __LINE__, pThreadInfo->filePath);
1186 1187 1188
      return;
  }

1189 1190 1191
  fprintf(pThreadInfo->fp, "%s", resultBuf);
  tmfclose(pThreadInfo->fp);
  pThreadInfo->fp = NULL;
1192 1193
}

1194
static void fetchResult(TAOS_RES *res, threadInfo* pThreadInfo) {
1195 1196 1197 1198 1199
  TAOS_ROW    row = NULL;
  int         num_rows = 0;
  int         num_fields = taos_field_count(res);
  TAOS_FIELD *fields     = taos_fetch_fields(res);

1200 1201
  char* databuf = (char*) calloc(1, 100*1024*1024);
  if (databuf == NULL) {
1202 1203
    errorPrint("%s() LN%d, failed to malloc, warning: save result to file slowly!\n",
            __func__, __LINE__);
1204 1205
    return ;
  }
H
hzcheng 已提交
1206

1207
  int   totalLen = 0;
H
hzcheng 已提交
1208

1209
  // fetch the records row by row
1210
  while((row = taos_fetch_row(res))) {
1211
    if ((strlen(pThreadInfo->filePath) > 0)
1212
            && (totalLen >= 100*1024*1024 - 32000)) {
1213
        appendResultBufToFile(databuf, pThreadInfo);
1214 1215
        totalLen = 0;
        memset(databuf, 0, 100*1024*1024);
H
hzcheng 已提交
1216
    }
1217
    num_rows++;
J
jiaoqiyuan 已提交
1218
    char temp[16000] = {0};
1219 1220 1221 1222 1223
    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 已提交
1224 1225
  }

1226
  verbosePrint("%s() LN%d, databuf=%s resultFile=%s\n",
1227 1228 1229
          __func__, __LINE__, databuf, pThreadInfo->filePath);
  if (strlen(pThreadInfo->filePath) > 0) {
    appendResultBufToFile(databuf, pThreadInfo);
1230
  }
1231 1232
  free(databuf);
}
H
hzcheng 已提交
1233

1234
static void selectAndGetResult(
1235 1236
        threadInfo *pThreadInfo, char *command)
{
1237 1238 1239 1240 1241 1242 1243 1244 1245
  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;
    }

1246
    fetchResult(res, pThreadInfo);
1247
    taos_free_result(res);
1248

1249 1250 1251
  } else if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
      int retCode = postProceSql(
              g_queryInfo.host, &(g_queryInfo.serv_addr), g_queryInfo.port,
1252
              command,
1253
              pThreadInfo);
1254 1255 1256 1257 1258 1259 1260 1261
      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);
  }
1262
}
H
hzcheng 已提交
1263

1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302
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;
1303
  return randfloat[cursor];
1304 1305
}

1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322
#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

1323
static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1324

1325
static void rand_string(char *str, int size) {
1326 1327 1328 1329
  str[0] = 0;
  if (size > 0) {
    //--size;
    int n;
1330
    for (n = 0; n < size; n++) {
1331
      int key = abs(rand_tinyint()) % (int)(sizeof(charset) - 1);
1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347
      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++){
1348 1349 1350 1351
    randint[i] = (int)(taosRandom() % 65535);
    randbigint[i] = (int64_t)(taosRandom() % 2147483648);
    randfloat[i] = (float)(taosRandom() / 1000.0);
    randdouble[i] = (double)(taosRandom() / 1000000.0);
1352 1353 1354
  }
}

1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374
#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)

1375
static int printfInsertMeta() {
1376
    SHOW_PARSE_RESULT_START();
1377

1378
  printf("interface:                  \033[33m%s\033[0m\n",
S
Shuduo Sang 已提交
1379
          (g_args.iface==TAOSC_IFACE)?"taosc":(g_args.iface==REST_IFACE)?"rest":"stmt");
1380 1381
  printf("host:                       \033[33m%s:%u\033[0m\n",
          g_Dbs.host, g_Dbs.port);
1382 1383
  printf("user:                       \033[33m%s\033[0m\n", g_Dbs.user);
  printf("password:                   \033[33m%s\033[0m\n", g_Dbs.password);
1384
  printf("configDir:                  \033[33m%s\033[0m\n", configDir);
1385 1386
  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);
1387 1388
  printf("thread num of create table: \033[33m%d\033[0m\n",
          g_Dbs.threadCountByCreateTbl);
1389
  printf("top insert interval:        \033[33m%"PRIu64"\033[0m\n",
1390
          g_args.insert_interval);
1391
  printf("number of records per req:  \033[33m%u\033[0m\n",
1392
          g_args.num_of_RPR);
1393
  printf("max sql length:             \033[33m%"PRIu64"\033[0m\n",
1394
          g_args.max_sql_len);
1395 1396

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

1398 1399
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    printf("database[\033[33m%d\033[0m]:\n", i);
1400 1401
    printf("  database[%d] name:      \033[33m%s\033[0m\n",
            i, g_Dbs.db[i].dbName);
1402
    if (0 == g_Dbs.db[i].drop) {
1403 1404 1405
      printf("  drop:                  \033[33mno\033[0m\n");
    } else {
      printf("  drop:                  \033[33myes\033[0m\n");
1406 1407 1408
    }

    if (g_Dbs.db[i].dbCfg.blocks > 0) {
1409 1410
      printf("  blocks:                \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.blocks);
1411 1412
    }
    if (g_Dbs.db[i].dbCfg.cache > 0) {
1413 1414
      printf("  cache:                 \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.cache);
1415 1416
    }
    if (g_Dbs.db[i].dbCfg.days > 0) {
1417 1418
      printf("  days:                  \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.days);
1419 1420
    }
    if (g_Dbs.db[i].dbCfg.keep > 0) {
1421 1422
      printf("  keep:                  \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.keep);
1423 1424
    }
    if (g_Dbs.db[i].dbCfg.replica > 0) {
1425 1426
      printf("  replica:               \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.replica);
1427 1428
    }
    if (g_Dbs.db[i].dbCfg.update > 0) {
1429 1430
      printf("  update:                \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.update);
1431 1432
    }
    if (g_Dbs.db[i].dbCfg.minRows > 0) {
1433 1434
      printf("  minRows:               \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.minRows);
1435 1436
    }
    if (g_Dbs.db[i].dbCfg.maxRows > 0) {
1437 1438
      printf("  maxRows:               \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.maxRows);
1439 1440 1441 1442 1443
    }
    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) {
1444 1445
      printf("  walLevel:              \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.walLevel);
1446 1447
    }
    if (g_Dbs.db[i].dbCfg.fsync > 0) {
1448 1449
      printf("  fsync:                 \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.fsync);
1450 1451
    }
    if (g_Dbs.db[i].dbCfg.quorum > 0) {
1452 1453
      printf("  quorum:                \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.quorum);
1454 1455
    }
    if (g_Dbs.db[i].dbCfg.precision[0] != 0) {
1456
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
1457
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1458
        printf("  precision:             \033[33m%s\033[0m\n",
1459
            g_Dbs.db[i].dbCfg.precision);
1460
      } else {
1461
        printf("\033[1m\033[40;31m  precision error:       %s\033[0m\n",
1462
                g_Dbs.db[i].dbCfg.precision);
1463
        return -1;
1464 1465 1466
      }
    }

1467
    printf("  super table count:     \033[33m%"PRIu64"\033[0m\n",
1468
        g_Dbs.db[i].superTblCount);
1469 1470
    for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      printf("  super table[\033[33m%"PRIu64"\033[0m]:\n", j);
1471

1472
      printf("      stbName:           \033[33m%s\033[0m\n",
1473
          g_Dbs.db[i].superTbls[j].sTblName);
1474 1475 1476

      if (PRE_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) {
        printf("      autoCreateTable:   \033[33m%s\033[0m\n",  "no");
1477 1478
      } else if (AUTO_CREATE_SUBTBL ==
              g_Dbs.db[i].superTbls[j].autoCreateTable) {
1479 1480 1481 1482
        printf("      autoCreateTable:   \033[33m%s\033[0m\n",  "yes");
      } else {
        printf("      autoCreateTable:   \033[33m%s\033[0m\n",  "error");
      }
1483

1484 1485 1486 1487 1488 1489 1490
      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");
      }
1491

1492
      printf("      childTblCount:     \033[33m%"PRId64"\033[0m\n",
1493
              g_Dbs.db[i].superTbls[j].childTblCount);
1494
      printf("      childTblPrefix:    \033[33m%s\033[0m\n",
1495
              g_Dbs.db[i].superTbls[j].childTblPrefix);
1496
      printf("      dataSource:        \033[33m%s\033[0m\n",
1497
              g_Dbs.db[i].superTbls[j].dataSource);
1498 1499 1500
      printf("      iface:             \033[33m%s\033[0m\n",
          (g_Dbs.db[i].superTbls[j].iface==TAOSC_IFACE)?"taosc":
          (g_Dbs.db[i].superTbls[j].iface==REST_IFACE)?"rest":"stmt");
1501
      if (g_Dbs.db[i].superTbls[j].childTblLimit > 0) {
1502
        printf("      childTblLimit:     \033[33m%"PRId64"\033[0m\n",
1503
                g_Dbs.db[i].superTbls[j].childTblLimit);
1504
      }
1505
      if (g_Dbs.db[i].superTbls[j].childTblOffset > 0) {
1506
        printf("      childTblOffset:    \033[33m%"PRIu64"\033[0m\n",
1507
                g_Dbs.db[i].superTbls[j].childTblOffset);
1508
      }
1509
      printf("      insertRows:        \033[33m%"PRId64"\033[0m\n",
1510
              g_Dbs.db[i].superTbls[j].insertRows);
1511
/*
1512
      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1513
        printf("      multiThreadWriteOneTbl:  \033[33mno\033[0m\n");
1514
      }else {
1515
        printf("      multiThreadWriteOneTbl:  \033[33myes\033[0m\n");
1516
      }
1517
      */
1518
      printf("      interlaceRows:     \033[33m%u\033[0m\n",
1519
              g_Dbs.db[i].superTbls[j].interlaceRows);
1520 1521

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

1526
      printf("      disorderRange:     \033[33m%d\033[0m\n",
1527
              g_Dbs.db[i].superTbls[j].disorderRange);
1528
      printf("      disorderRatio:     \033[33m%d\033[0m\n",
1529
              g_Dbs.db[i].superTbls[j].disorderRatio);
1530
      printf("      maxSqlLen:         \033[33m%"PRIu64"\033[0m\n",
1531
              g_Dbs.db[i].superTbls[j].maxSqlLen);
1532
      printf("      timeStampStep:     \033[33m%"PRId64"\033[0m\n",
1533
              g_Dbs.db[i].superTbls[j].timeStampStep);
1534
      printf("      startTimestamp:    \033[33m%s\033[0m\n",
1535
              g_Dbs.db[i].superTbls[j].startTimestamp);
1536
      printf("      sampleFormat:      \033[33m%s\033[0m\n",
1537
              g_Dbs.db[i].superTbls[j].sampleFormat);
1538
      printf("      sampleFile:        \033[33m%s\033[0m\n",
1539
              g_Dbs.db[i].superTbls[j].sampleFile);
1540
      printf("      tagsFile:          \033[33m%s\033[0m\n",
1541
              g_Dbs.db[i].superTbls[j].tagsFile);
1542
      printf("      columnCount:       \033[33m%d\033[0m\n",
1543
              g_Dbs.db[i].superTbls[j].columnCount);
1544 1545
      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);
1546
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType,
1547 1548 1549
                       "binary", 6))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType,
                       "nchar", 5))) {
1550
          printf("column[\033[33m%d\033[0m]:\033[33m%s(%d)\033[0m ", k,
1551 1552
                  g_Dbs.db[i].superTbls[j].columns[k].dataType,
                  g_Dbs.db[i].superTbls[j].columns[k].dataLen);
1553
        } else {
1554
          printf("column[%d]:\033[33m%s\033[0m ", k,
1555
                  g_Dbs.db[i].superTbls[j].columns[k].dataType);
1556 1557 1558
        }
      }
      printf("\n");
1559 1560

      printf("      tagCount:            \033[33m%d\033[0m\n        ",
1561
              g_Dbs.db[i].superTbls[j].tagCount);
1562 1563
      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);
1564
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
1565 1566 1567
                        "binary", strlen("binary")))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                        "nchar", strlen("nchar")))) {
1568
          printf("tag[%d]:\033[33m%s(%d)\033[0m ", k,
1569 1570
                  g_Dbs.db[i].superTbls[j].tags[k].dataType,
                  g_Dbs.db[i].superTbls[j].tags[k].dataLen);
1571
        } else {
1572
          printf("tag[%d]:\033[33m%s\033[0m ", k,
1573
                  g_Dbs.db[i].superTbls[j].tags[k].dataType);
1574
        }
1575 1576 1577 1578 1579
      }
      printf("\n");
    }
    printf("\n");
  }
1580 1581

  SHOW_PARSE_RESULT_END();
1582 1583

  return 0;
1584 1585 1586
}

static void printfInsertMetaToFile(FILE* fp) {
1587 1588

  SHOW_PARSE_RESULT_START_TO_FILE(fp);
1589

1590 1591
  fprintf(fp, "host:                       %s:%u\n", g_Dbs.host, g_Dbs.port);
  fprintf(fp, "user:                       %s\n", g_Dbs.user);
1592
  fprintf(fp, "configDir:                  %s\n", configDir);
1593 1594 1595
  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);
1596
  fprintf(fp, "number of records per req:  %u\n", g_args.num_of_RPR);
1597
  fprintf(fp, "max sql length:             %"PRIu64"\n", g_args.max_sql_len);
1598
  fprintf(fp, "database count:          %d\n", g_Dbs.dbCount);
1599

1600 1601
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    fprintf(fp, "database[%d]:\n", i);
1602
    fprintf(fp, "  database[%d] name:       %s\n", i, g_Dbs.db[i].dbName);
1603
    if (0 == g_Dbs.db[i].drop) {
1604
      fprintf(fp, "  drop:                  no\n");
1605
    }else {
1606
      fprintf(fp, "  drop:                  yes\n");
1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645
    }

    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) {
1646
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
1647
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1648 1649
        fprintf(fp, "  precision:             %s\n",
                g_Dbs.db[i].dbCfg.precision);
1650
      } else {
1651 1652
        fprintf(fp, "  precision error:       %s\n",
                g_Dbs.db[i].dbCfg.precision);
1653 1654 1655
      }
    }

1656 1657
    fprintf(fp, "  super table count:     %"PRIu64"\n",
            g_Dbs.db[i].superTblCount);
1658 1659
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      fprintf(fp, "  super table[%d]:\n", j);
1660

1661 1662
      fprintf(fp, "      stbName:           %s\n",
              g_Dbs.db[i].superTbls[j].sTblName);
1663 1664 1665

      if (PRE_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) {
        fprintf(fp, "      autoCreateTable:   %s\n",  "no");
1666 1667
      } else if (AUTO_CREATE_SUBTBL
              == g_Dbs.db[i].superTbls[j].autoCreateTable) {
1668 1669 1670 1671
        fprintf(fp, "      autoCreateTable:   %s\n",  "yes");
      } else {
        fprintf(fp, "      autoCreateTable:   %s\n",  "error");
      }
1672

1673 1674
      if (TBL_NO_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
        fprintf(fp, "      childTblExists:    %s\n",  "no");
1675 1676
      } else if (TBL_ALREADY_EXISTS
              == g_Dbs.db[i].superTbls[j].childTblExists) {
1677 1678 1679 1680
        fprintf(fp, "      childTblExists:    %s\n",  "yes");
      } else {
        fprintf(fp, "      childTblExists:    %s\n",  "error");
      }
1681

1682
      fprintf(fp, "      childTblCount:     %"PRId64"\n",
1683 1684 1685 1686 1687
              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);
1688 1689 1690
      fprintf(fp, "      iface:             %s\n",
          (g_Dbs.db[i].superTbls[j].iface==TAOSC_IFACE)?"taosc":
          (g_Dbs.db[i].superTbls[j].iface==REST_IFACE)?"rest":"stmt");
1691
      fprintf(fp, "      insertRows:        %"PRId64"\n",
1692
              g_Dbs.db[i].superTbls[j].insertRows);
1693
      fprintf(fp, "      interlace rows:    %u\n",
1694
              g_Dbs.db[i].superTbls[j].interlaceRows);
1695
      if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) {
1696
        fprintf(fp, "      stable insert interval:   %"PRIu64"\n",
1697
                g_Dbs.db[i].superTbls[j].insertInterval);
1698
      }
1699
/*
1700
      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1701
        fprintf(fp, "      multiThreadWriteOneTbl:  no\n");
1702
      }else {
1703
        fprintf(fp, "      multiThreadWriteOneTbl:  yes\n");
1704
      }
1705
      */
1706
      fprintf(fp, "      interlaceRows:     %u\n",
1707
              g_Dbs.db[i].superTbls[j].interlaceRows);
1708 1709 1710 1711
      fprintf(fp, "      disorderRange:     %d\n",
              g_Dbs.db[i].superTbls[j].disorderRange);
      fprintf(fp, "      disorderRatio:     %d\n",
              g_Dbs.db[i].superTbls[j].disorderRatio);
1712
      fprintf(fp, "      maxSqlLen:         %"PRIu64"\n",
1713
              g_Dbs.db[i].superTbls[j].maxSqlLen);
1714

1715 1716 1717 1718
      fprintf(fp, "      timeStampStep:     %"PRId64"\n",
              g_Dbs.db[i].superTbls[j].timeStampStep);
      fprintf(fp, "      startTimestamp:    %s\n",
              g_Dbs.db[i].superTbls[j].startTimestamp);
1719 1720 1721 1722 1723 1724
      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);
1725

1726 1727
      fprintf(fp, "      columnCount:       %d\n        ",
              g_Dbs.db[i].superTbls[j].columnCount);
1728 1729
      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);
1730
        if ((0 == strncasecmp(
1731 1732
                        g_Dbs.db[i].superTbls[j].columns[k].dataType,
                        "binary", strlen("binary")))
1733 1734
                || (0 == strncasecmp(
                        g_Dbs.db[i].superTbls[j].columns[k].dataType,
1735
                        "nchar", strlen("nchar")))) {
1736 1737 1738
          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);
1739
        } else {
1740 1741
          fprintf(fp, "column[%d]:%s ",
                  k, g_Dbs.db[i].superTbls[j].columns[k].dataType);
1742 1743 1744
        }
      }
      fprintf(fp, "\n");
1745 1746 1747

      fprintf(fp, "      tagCount:            %d\n        ",
              g_Dbs.db[i].superTbls[j].tagCount);
1748 1749
      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);
1750
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
1751 1752 1753
                        "binary", strlen("binary")))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                        "nchar", strlen("nchar")))) {
1754 1755
          fprintf(fp, "tag[%d]:%s(%d) ",
                  k, g_Dbs.db[i].superTbls[j].tags[k].dataType,
1756
                  g_Dbs.db[i].superTbls[j].tags[k].dataLen);
1757 1758
        } else {
          fprintf(fp, "tag[%d]:%s ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType);
1759
        }
1760 1761 1762 1763 1764
      }
      fprintf(fp, "\n");
    }
    fprintf(fp, "\n");
  }
1765

1766
  SHOW_PARSE_RESULT_END_TO_FILE(fp);
1767 1768 1769
}

static void printfQueryMeta() {
1770

1771
  SHOW_PARSE_RESULT_START();
1772

1773
  printf("host:                    \033[33m%s:%u\033[0m\n",
1774
          g_queryInfo.host, g_queryInfo.port);
1775 1776 1777 1778
  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");
1779 1780 1781

  if ((SUBSCRIBE_TEST == g_args.test_mode) || (QUERY_TEST == g_args.test_mode)) {
    printf("specified table query info:                   \n");
1782
    printf("sqlCount:       \033[33m%d\033[0m\n",
1783
      g_queryInfo.specifiedQueryInfo.sqlCount);
1784 1785 1786
    if (g_queryInfo.specifiedQueryInfo.sqlCount > 0) {
      printf("specified tbl query times:\n");
      printf("                \033[33m%"PRIu64"\033[0m\n",
1787
      g_queryInfo.specifiedQueryInfo.queryTimes);
1788 1789 1790
      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);
1791
      printf("concurrent:     \033[33m%d\033[0m\n",
1792 1793
      g_queryInfo.specifiedQueryInfo.concurrent);
      printf("mod:            \033[33m%s\033[0m\n",
1794
        (g_queryInfo.specifiedQueryInfo.asyncMode)?"async":"sync");
1795
      printf("interval:       \033[33m%"PRIu64"\033[0m\n",
1796
        g_queryInfo.specifiedQueryInfo.subscribeInterval);
1797
      printf("restart:        \033[33m%d\033[0m\n",
1798
        g_queryInfo.specifiedQueryInfo.subscribeRestart);
1799
      printf("keepProgress:   \033[33m%d\033[0m\n",
1800
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
1801

1802 1803
      for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
        printf("  sql[%d]: \033[33m%s\033[0m\n",
1804 1805 1806 1807 1808 1809
            i, g_queryInfo.specifiedQueryInfo.sql[i]);
      }
      printf("\n");
    }

    printf("super table query info:\n");
1810
    printf("sqlCount:       \033[33m%d\033[0m\n",
1811 1812 1813 1814 1815 1816 1817
      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);
1818
      printf("childTblCount:  \033[33m%"PRId64"\033[0m\n",
1819 1820 1821 1822 1823 1824 1825
        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",
1826
        (g_queryInfo.superQueryInfo.asyncMode)?"async":"sync");
1827
      printf("interval:       \033[33m%"PRIu64"\033[0m\n",
1828
        g_queryInfo.superQueryInfo.subscribeInterval);
1829
      printf("restart:        \033[33m%d\033[0m\n",
1830
        g_queryInfo.superQueryInfo.subscribeRestart);
1831
      printf("keepProgress:   \033[33m%d\033[0m\n",
1832
        g_queryInfo.superQueryInfo.subscribeKeepProgress);
1833

1834 1835 1836 1837 1838 1839
      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");
    }
1840
  }
1841

1842
  SHOW_PARSE_RESULT_END();
1843 1844
}

1845
static char* formatTimestamp(char* buf, int64_t val, int precision) {
1846
  time_t tt;
1847 1848 1849
  if (precision == TSDB_TIME_PRECISION_NANO) {
    tt = (time_t)(val / 1000000000);
  } else if (precision == TSDB_TIME_PRECISION_MICRO) {
1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869
    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);

1870 1871 1872
  if (precision == TSDB_TIME_PRECISION_NANO) {
    sprintf(buf + pos, ".%09d", (int)(val % 1000000000));
  } else if (precision == TSDB_TIME_PRECISION_MICRO) {
1873 1874 1875 1876 1877 1878 1879 1880
    sprintf(buf + pos, ".%06d", (int)(val % 1000000));
  } else {
    sprintf(buf + pos, ".%03d", (int)(val % 1000));
  }

  return buf;
}

1881
static void xDumpFieldToFile(FILE* fp, const char* val,
1882
        TAOS_FIELD* field, int32_t length, int precision) {
1883

1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918
  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:
1919
      formatTimestamp(buf, *(int64_t*)val, precision);
1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934
      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) {
1935
    errorPrint("%s() LN%d, failed to open file: %s\n", __func__, __LINE__, fname);
1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949
    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);
1950

1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970
  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;
}

1971 1972
static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) {
  TAOS_RES * res;
1973 1974
  TAOS_ROW row = NULL;
  int count = 0;
1975 1976

  res = taos_query(taos, "show databases;");
1977
  int32_t code = taos_errno(res);
1978

1979
  if (code != 0) {
1980
    errorPrint( "failed to run <show databases>, reason: %s\n", taos_errstr(res));
1981 1982 1983 1984 1985
    return -1;
  }

  TAOS_FIELD *fields = taos_fetch_fields(res);

1986
  while((row = taos_fetch_row(res)) != NULL) {
1987
    // sys database name : 'log'
1988
    if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "log",
1989
                fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) {
1990 1991
      continue;
    }
1992 1993 1994

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

1999
    tstrncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX],
2000
            fields[TSDB_SHOW_DB_NAME_INDEX].bytes);
2001
    formatTimestamp(dbInfos[count]->create_time,
2002 2003
            *(int64_t*)row[TSDB_SHOW_DB_CREATED_TIME_INDEX],
            TSDB_TIME_PRECISION_MILLI);
S
Shuduo Sang 已提交
2004
    dbInfos[count]->ntables = *((int64_t *)row[TSDB_SHOW_DB_NTABLES_INDEX]);
2005
    dbInfos[count]->vgroups = *((int32_t *)row[TSDB_SHOW_DB_VGROUPS_INDEX]);
2006 2007
    dbInfos[count]->replica = *((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX]);
    dbInfos[count]->quorum = *((int16_t *)row[TSDB_SHOW_DB_QUORUM_INDEX]);
2008
    dbInfos[count]->days = *((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]);
2009

2010
    tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX],
2011
            fields[TSDB_SHOW_DB_KEEP_INDEX].bytes);
2012 2013 2014 2015 2016 2017 2018
    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]));
2019
    dbInfos[count]->cachelast =
2020
      (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_CACHELAST_INDEX]));
2021

2022
    tstrncpy(dbInfos[count]->precision,
2023 2024
            (char *)row[TSDB_SHOW_DB_PRECISION_INDEX],
            fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes);
2025
    dbInfos[count]->update = *((int8_t *)row[TSDB_SHOW_DB_UPDATE_INDEX]);
2026
    tstrncpy(dbInfos[count]->status, (char *)row[TSDB_SHOW_DB_STATUS_INDEX],
2027
            fields[TSDB_SHOW_DB_STATUS_INDEX].bytes);
2028

2029 2030
    count++;
    if (count > MAX_DATABASE_COUNT) {
2031
      errorPrint("%s() LN%d, The database count overflow than %d\n",
2032
         __func__, __LINE__, MAX_DATABASE_COUNT);
2033 2034 2035 2036 2037 2038 2039
      break;
    }
  }

  return count;
}

2040
static void printfDbInfoForQueryToFile(
2041
        char* filename, SDbInfo* dbInfos, int index) {
2042

2043
  if (filename[0] == 0)
2044
      return;
2045 2046 2047

  FILE *fp = fopen(filename, "at");
  if (fp == NULL) {
2048
    errorPrint( "failed to open file: %s\n", filename);
2049
    return;
2050 2051 2052 2053 2054
  }

  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 已提交
2055
  fprintf(fp, "ntables: %"PRId64"\n", dbInfos->ntables);
2056
  fprintf(fp, "vgroups: %d\n", dbInfos->vgroups);
2057 2058
  fprintf(fp, "replica: %d\n", dbInfos->replica);
  fprintf(fp, "quorum: %d\n", dbInfos->quorum);
2059 2060
  fprintf(fp, "days: %d\n", dbInfos->days);
  fprintf(fp, "keep0,keep1,keep(D): %s\n", dbInfos->keeplist);
2061 2062 2063 2064 2065 2066 2067
  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);
2068 2069
  fprintf(fp, "cachelast: %d\n", dbInfos->cachelast);
  fprintf(fp, "precision: %s\n", dbInfos->precision);
2070
  fprintf(fp, "update: %d\n", dbInfos->update);
2071
  fprintf(fp, "status: %s\n", dbInfos->status);
2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085
  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);
2086
  snprintf(filename, MAX_QUERY_SQL_LENGTH, "querySystemInfo-%d-%d-%d %d:%d:%d",
2087 2088
          lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min,
          lt->tm_sec);
2089

2090 2091
  // show variables
  res = taos_query(taos, "show variables;");
2092
  //fetchResult(res, filename);
2093 2094 2095 2096 2097
  xDumpResultToFile(filename, res);

  // show dnodes
  res = taos_query(taos, "show dnodes;");
  xDumpResultToFile(filename, res);
2098
  //fetchResult(res, filename);
2099

2100 2101 2102 2103
  // show databases
  res = taos_query(taos, "show databases;");
  SDbInfo** dbInfos = (SDbInfo **)calloc(MAX_DATABASE_COUNT, sizeof(SDbInfo *));
  if (dbInfos == NULL) {
2104
    errorPrint("%s() LN%d, failed to allocate memory\n", __func__, __LINE__);
2105 2106 2107
    return;
  }
  int dbCount = getDbFromServer(taos, dbInfos);
2108
  if (dbCount <= 0) {
2109 2110
      free(dbInfos);
      return;
2111
  }
2112 2113

  for (int i = 0; i < dbCount; i++) {
2114
    // printf database info
2115
    printfDbInfoForQueryToFile(filename, dbInfos[i], i);
2116

2117 2118 2119 2120
    // show db.vgroups
    snprintf(buffer, MAX_QUERY_SQL_LENGTH, "show %s.vgroups;", dbInfos[i]->name);
    res = taos_query(taos, buffer);
    xDumpResultToFile(filename, res);
2121

2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132
    // 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);
}

2133
static int postProceSql(char *host, struct sockaddr_in *pServAddr, uint16_t port,
2134
        char* sqlstr, threadInfo *pThreadInfo)
2135
{
2136
    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";
2137

2138
    char *url = "/rest/sql";
2139

2140 2141 2142 2143
    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;
2144

2145
    int req_buf_len = strlen(sqlstr) + REQ_EXTRA_BUF_LEN;
2146

2147 2148 2149 2150 2151
    request_buf = malloc(req_buf_len);
    if (NULL == request_buf) {
      errorPrint("%s", "ERROR, cannot allocate memory.\n");
      exit(EXIT_FAILURE);
    }
2152

2153 2154
    char userpass_buf[INPUT_BUF_LEN];
    int mod_table[] = {0, 2, 1};
2155

2156 2157 2158 2159 2160 2161 2162 2163
    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', '+', '/'};
2164

2165 2166 2167 2168
    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);
2169

2170
    char base64_buf[INPUT_BUF_LEN];
2171
#ifdef WINDOWS
2172
    WSADATA wsaData;
2173
    WSAStartup(MAKEWORD(2, 2), &wsaData);
2174 2175
    SOCKET sockfd;
#else
2176
    int sockfd;
2177
#endif
2178 2179
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
2180
#ifdef WINDOWS
2181
        errorPrint( "Could not create socket : %d" , WSAGetLastError());
2182
#endif
2183 2184 2185 2186
        debugPrint("%s() LN%d, sockfd=%d\n", __func__, __LINE__, sockfd);
        free(request_buf);
        ERROR_EXIT("ERROR opening socket");
    }
2187

2188
    int retConn = connect(sockfd, (struct sockaddr *)pServAddr, sizeof(struct sockaddr));
2189 2190 2191 2192 2193
    debugPrint("%s() LN%d connect() return %d\n", __func__, __LINE__, retConn);
    if (retConn < 0) {
        free(request_buf);
        ERROR_EXIT("ERROR connecting");
    }
2194

2195
    memset(base64_buf, 0, INPUT_BUF_LEN);
2196

2197 2198 2199 2200 2201 2202 2203 2204
    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;
2205

2206 2207 2208 2209 2210
      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];
    }
2211

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

2215 2216 2217
    debugPrint("%s() LN%d: auth string base64 encoded: %s\n",
            __func__, __LINE__, base64_buf);
    char *auth = base64_buf;
2218

2219 2220 2221 2222 2223 2224 2225 2226 2227
    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);
2228

2229 2230 2231
    req_str_len = strlen(request_buf);
    sent = 0;
    do {
2232
#ifdef WINDOWS
2233
        bytes = send(sockfd, request_buf + sent, req_str_len - sent, 0);
2234
#else
2235
        bytes = write(sockfd, request_buf + sent, req_str_len - sent);
2236
#endif
2237 2238 2239 2240 2241 2242
        if (bytes < 0)
            ERROR_EXIT("ERROR writing message to socket");
        if (bytes == 0)
            break;
        sent+=bytes;
    } while(sent < req_str_len);
2243

2244 2245 2246 2247
    memset(response_buf, 0, RESP_BUF_LEN);
    resp_len = sizeof(response_buf) - 1;
    received = 0;
    do {
2248
#ifdef WINDOWS
2249
        bytes = recv(sockfd, response_buf + received, resp_len - received, 0);
2250
#else
2251
        bytes = read(sockfd, response_buf + received, resp_len - received);
2252
#endif
2253 2254 2255 2256 2257 2258 2259 2260
        if (bytes < 0) {
            free(request_buf);
            ERROR_EXIT("ERROR reading response from socket");
        }
        if (bytes == 0)
            break;
        received += bytes;
    } while(received < resp_len);
2261

2262 2263 2264 2265
    if (received == resp_len) {
        free(request_buf);
        ERROR_EXIT("ERROR storing complete response from socket");
    }
H
Haojun Liao 已提交
2266

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

2270 2271
    if (strlen(pThreadInfo->filePath) > 0) {
       appendResultBufToFile(response_buf, pThreadInfo);
2272 2273
    }

2274
    free(request_buf);
2275
#ifdef WINDOWS
2276
    closesocket(sockfd);
2277 2278
    WSACleanup();
#else
2279
    close(sockfd);
2280
#endif
2281

2282
    return 0;
2283 2284
}

2285
static char* getTagValueFromTagSample(SSuperTable* stbInfo, int tagUsePos) {
2286 2287
  char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
  if (NULL == dataBuf) {
2288
    errorPrint("%s() LN%d, calloc failed! size:%d\n",
2289
        __func__, __LINE__, TSDB_MAX_SQL_LEN+1);
2290 2291
    return NULL;
  }
2292

2293
  int    dataLen = 0;
2294
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2295
          "(%s)", stbInfo->tagDataBuf + stbInfo->lenOfTagOfOneRow * tagUsePos);
2296

2297 2298 2299
  return dataBuf;
}

2300
static char* generateTagVaulesForStb(SSuperTable* stbInfo, int32_t tableSeq) {
2301 2302 2303 2304 2305 2306 2307 2308 2309
  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++) {
2310
    if ((0 == strncasecmp(stbInfo->tags[i].dataType, "binary", strlen("binary")))
2311
            || (0 == strncasecmp(stbInfo->tags[i].dataType, "nchar", strlen("nchar")))) {
2312
      if (stbInfo->tags[i].dataLen > TSDB_MAX_BINARY_LEN) {
2313
        printf("binary or nchar length overflow, max size:%u\n",
2314
                (uint32_t)TSDB_MAX_BINARY_LEN);
2315 2316 2317
        tmfree(dataBuf);
        return NULL;
      }
2318

2319 2320
      int tagBufLen = stbInfo->tags[i].dataLen + 1;
      char* buf = (char*)calloc(tagBufLen, 1);
2321 2322 2323 2324 2325
      if (NULL == buf) {
        printf("calloc failed! size:%d\n", stbInfo->tags[i].dataLen);
        tmfree(dataBuf);
        return NULL;
      }
2326 2327 2328 2329 2330 2331 2332

      if (tableSeq % 2) {
        tstrncpy(buf, "beijing", tagBufLen);
      } else {
        tstrncpy(buf, "shanghai", tagBufLen);
      }
      //rand_string(buf, stbInfo->tags[i].dataLen);
2333
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2334
              "\'%s\', ", buf);
2335
      tmfree(buf);
2336
    } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2337
                "int", strlen("int"))) {
2338
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2339
              "%d, ", tableSeq);
2340
    } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2341
                "bigint", strlen("bigint"))) {
2342
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2343
              "%"PRId64", ", rand_bigint());
2344
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2345
                "float", strlen("float"))) {
2346
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2347
              "%f, ", rand_float());
2348
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2349
                "double", strlen("double"))) {
2350
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2351
              "%f, ", rand_double());
2352
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2353
                "smallint", strlen("smallint"))) {
2354
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2355
              "%d, ", rand_smallint());
2356
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2357
                "tinyint", strlen("tinyint"))) {
2358
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2359
              "%d, ", rand_tinyint());
2360
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2361
                "bool", strlen("bool"))) {
2362
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2363
              "%d, ", rand_bool());
2364
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2365
                "timestamp", strlen("timestamp"))) {
2366
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2367
              "%"PRId64", ", rand_bigint());
2368 2369 2370 2371 2372 2373
    }  else {
      printf("No support data type: %s\n", stbInfo->tags[i].dataType);
      tmfree(dataBuf);
      return NULL;
    }
  }
2374

2375
  dataLen -= 2;
2376
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")");
2377 2378 2379
  return dataBuf;
}

2380
static int calcRowLen(SSuperTable*  superTbls) {
2381 2382
  int colIndex;
  int  lenOfOneRow = 0;
2383

2384 2385
  for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) {
    char* dataType = superTbls->columns[colIndex].dataType;
2386

2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402
    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;
2403
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2404
      lenOfOneRow += 42;
2405
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418
      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;
2419

2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435
    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;
2436
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2437 2438 2439 2440 2441 2442 2443 2444
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 42;
    } else {
      printf("get error tag type : %s\n", dataType);
      exit(-1);
    }
  }

  superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow;
2445

2446 2447 2448 2449
  return 0;
}


2450
static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos,
2451
        char* dbName, char* sTblName, char** childTblNameOfSuperTbl,
2452
        int64_t* childTblCountOfSuperTbl, int64_t limit, uint64_t offset) {
2453

2454
  char command[BUFFER_SIZE] = "\0";
2455 2456
  char limitBuf[100] = "\0";

2457
  TAOS_RES * res;
2458 2459 2460
  TAOS_ROW row = NULL;

  char* childTblName = *childTblNameOfSuperTbl;
2461 2462

  if (offset >= 0) {
2463
    snprintf(limitBuf, 100, " limit %"PRId64" offset %"PRIu64"",
2464
            limit, offset);
2465 2466
  }

2467
  //get all child table name use cmd: select tbname from superTblName;
2468
  snprintf(command, BUFFER_SIZE, "select tbname from %s.%s %s",
2469
          dbName, sTblName, limitBuf);
2470

2471
  res = taos_query(taos, command);
2472 2473 2474 2475
  int32_t code = taos_errno(res);
  if (code != 0) {
    taos_free_result(res);
    taos_close(taos);
2476
    errorPrint("%s() LN%d, failed to run command %s\n",
2477
           __func__, __LINE__, command);
2478 2479 2480
    exit(-1);
  }

2481 2482
  int64_t childTblCount = (limit < 0)?10000:limit;
  int64_t count = 0;
2483 2484 2485
  if (childTblName == NULL) {
    childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (NULL ==  childTblName) {
2486 2487 2488 2489
    taos_free_result(res);
        taos_close(taos);
        errorPrint("%s() LN%d, failed to allocate memory!\n", __func__, __LINE__);
        exit(-1);
2490 2491 2492
    }
  }

2493
  char* pTblName = childTblName;
2494
  while((row = taos_fetch_row(res)) != NULL) {
2495
    int32_t* len = taos_fetch_lengths(res);
2496 2497 2498 2499 2500 2501 2502

    if (0 == strlen((char *)row[0])) {
        errorPrint("%s() LN%d, No.%"PRId64" table return empty name\n",
            __func__, __LINE__, count);
        exit(-1);
    }

2503
    tstrncpy(pTblName, (char *)row[0], len[0]+1);
2504 2505 2506
    //printf("==== sub table name: %s\n", pTblName);
    count++;
    if (count >= childTblCount - 1) {
2507
      char *tmp = realloc(childTblName,
2508
              (size_t)childTblCount*1.5*TSDB_TABLE_NAME_LEN+1);
2509 2510 2511
      if (tmp != NULL) {
        childTblName = tmp;
        childTblCount = (int)(childTblCount*1.5);
2512
        memset(childTblName + count*TSDB_TABLE_NAME_LEN, 0,
2513
                (size_t)((childTblCount-count)*TSDB_TABLE_NAME_LEN));
2514 2515
      } else {
        // exit, if allocate more memory failed
2516
        errorPrint("%s() LN%d, realloc fail for save child table name of %s.%s\n",
2517
               __func__, __LINE__, dbName, sTblName);
2518 2519 2520 2521 2522 2523
        tmfree(childTblName);
        taos_free_result(res);
        taos_close(taos);
        exit(-1);
      }
    }
2524
    pTblName = childTblName + count * TSDB_TABLE_NAME_LEN;
2525
  }
2526

2527 2528 2529 2530 2531 2532 2533
  *childTblCountOfSuperTbl = count;
  *childTblNameOfSuperTbl  = childTblName;

  taos_free_result(res);
  return 0;
}

2534
static int getAllChildNameOfSuperTable(TAOS * taos, char* dbName,
2535
        char* sTblName, char** childTblNameOfSuperTbl,
2536
        int64_t* childTblCountOfSuperTbl) {
2537

2538 2539
    return getChildNameOfSuperTableWithLimitAndOffset(taos, dbName, sTblName,
            childTblNameOfSuperTbl, childTblCountOfSuperTbl,
2540
            -1, 0);
2541 2542
}

2543
static int getSuperTableFromServer(TAOS * taos, char* dbName,
2544
        SSuperTable*  superTbls) {
2545

2546
  char command[BUFFER_SIZE] = "\0";
2547
  TAOS_RES * res;
2548 2549
  TAOS_ROW row = NULL;
  int count = 0;
2550

2551
  //get schema use cmd: describe superTblName;
2552
  snprintf(command, BUFFER_SIZE, "describe %s.%s", dbName, superTbls->sTblName);
2553
  res = taos_query(taos, command);
2554 2555 2556
  int32_t code = taos_errno(res);
  if (code != 0) {
    printf("failed to run command %s\n", command);
2557
    taos_free_result(res);
2558 2559 2560 2561 2562 2563
    return -1;
  }

  int tagIndex = 0;
  int columnIndex = 0;
  TAOS_FIELD *fields = taos_fetch_fields(res);
2564
  while((row = taos_fetch_row(res)) != NULL) {
2565 2566 2567
    if (0 == count) {
      count++;
      continue;
2568
    }
2569 2570

    if (strcmp((char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX], "TAG") == 0) {
2571
      tstrncpy(superTbls->tags[tagIndex].field,
2572 2573
              (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
              fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
2574
      tstrncpy(superTbls->tags[tagIndex].dataType,
2575 2576
              (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes);
2577 2578 2579
      superTbls->tags[tagIndex].dataLen =
          *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
      tstrncpy(superTbls->tags[tagIndex].note,
2580 2581
              (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes);
2582
      tagIndex++;
2583
    } else {
2584
      tstrncpy(superTbls->columns[columnIndex].field,
2585 2586
              (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
              fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
2587
      tstrncpy(superTbls->columns[columnIndex].dataType,
2588 2589
              (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes);
2590 2591 2592
      superTbls->columns[columnIndex].dataLen =
          *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
      tstrncpy(superTbls->columns[columnIndex].note,
2593 2594
              (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes);
2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605
      columnIndex++;
    }
    count++;
  }

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

  calcRowLen(superTbls);

2606
/*
2607
  if (TBL_ALREADY_EXISTS == superTbls->childTblExists) {
2608
    //get all child table name use cmd: select tbname from superTblName;
2609 2610 2611
    int childTblCount = 10000;
    superTbls->childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (superTbls->childTblName == NULL) {
2612
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
2613 2614
      return -1;
    }
2615
    getAllChildNameOfSuperTable(taos, dbName,
2616 2617 2618
            superTbls->sTblName,
            &superTbls->childTblName,
            &superTbls->childTblCount);
2619
  }
2620
  */
2621 2622 2623
  return 0;
}

H
Haojun Liao 已提交
2624
static int createSuperTable(
2625 2626
        TAOS * taos, char* dbName,
        SSuperTable*  superTbl) {
H
Haojun Liao 已提交
2627

2628
  char command[BUFFER_SIZE] = "\0";
2629

2630 2631 2632 2633 2634
  char cols[STRING_LEN] = "\0";
  int colIndex;
  int len = 0;

  int  lenOfOneRow = 0;
2635 2636 2637

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

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

2645
    if (strcasecmp(dataType, "BINARY") == 0) {
2646
      len += snprintf(cols + len, STRING_LEN - len,
2647 2648
          ", col%d %s(%d)", colIndex, "BINARY",
          superTbl->columns[colIndex].dataLen);
2649
      lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
2650
    } else if (strcasecmp(dataType, "NCHAR") == 0) {
2651
      len += snprintf(cols + len, STRING_LEN - len,
2652 2653
          ", col%d %s(%d)", colIndex, "NCHAR",
          superTbl->columns[colIndex].dataLen);
2654
      lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672
    } 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;
2673
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2674 2675
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "DOUBLE");
      lenOfOneRow += 42;
2676
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2677 2678 2679 2680
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "TIMESTAMP");
      lenOfOneRow += 21;
    } else {
      taos_close(taos);
2681
      errorPrint("%s() LN%d, config error data type : %s\n",
2682
         __func__, __LINE__, dataType);
2683 2684 2685 2686
      exit(-1);
    }
  }

2687 2688
  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);
2689 2690

  // save for creating child table
2691 2692 2693
  superTbl->colsOfCreateChildTable = (char*)calloc(len+20, 1);
  if (NULL == superTbl->colsOfCreateChildTable) {
    errorPrint("%s() LN%d, Failed when calloc, size:%d",
2694
           __func__, __LINE__, len+1);
2695 2696 2697 2698
    taos_close(taos);
    exit(-1);
  }

2699
  snprintf(superTbl->colsOfCreateChildTable, len+20, "(ts timestamp%s)", cols);
2700
  verbosePrint("%s() LN%d: %s\n",
2701
      __func__, __LINE__, superTbl->colsOfCreateChildTable);
2702

2703 2704
  if (superTbl->tagCount == 0) {
    errorPrint("%s() LN%d, super table tag count is %d\n",
2705
            __func__, __LINE__, superTbl->tagCount);
2706 2707
    return -1;
  }
2708

2709 2710 2711
  char tags[STRING_LEN] = "\0";
  int tagIndex;
  len = 0;
2712

2713 2714 2715 2716
  int lenOfTagOfOneRow = 0;
  len += snprintf(tags + len, STRING_LEN - len, "(");
  for (tagIndex = 0; tagIndex < superTbl->tagCount; tagIndex++) {
    char* dataType = superTbl->tags[tagIndex].dataType;
2717

2718 2719
    if (strcasecmp(dataType, "BINARY") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
2720
              "BINARY", superTbl->tags[tagIndex].dataLen);
2721 2722 2723
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "NCHAR") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
2724
              "NCHAR", superTbl->tags[tagIndex].dataLen);
2725 2726 2727
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "INT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2728
              "INT");
2729 2730 2731
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 11;
    } else if (strcasecmp(dataType, "BIGINT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2732
              "BIGINT");
2733 2734 2735
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 21;
    } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2736
              "SMALLINT");
2737 2738 2739
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 6;
    } else if (strcasecmp(dataType, "TINYINT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2740
              "TINYINT");
2741 2742 2743
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 4;
    } else if (strcasecmp(dataType, "BOOL") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2744
              "BOOL");
2745 2746 2747
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 6;
    } else if (strcasecmp(dataType, "FLOAT") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2748
              "FLOAT");
2749 2750 2751
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 22;
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2752
              "DOUBLE");
2753 2754 2755
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 42;
    } else {
      taos_close(taos);
2756
      errorPrint("%s() LN%d, config error tag type : %s\n",
2757
         __func__, __LINE__, dataType);
2758
      exit(-1);
2759 2760
    }
  }
2761 2762 2763 2764 2765 2766 2767

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

  superTbl->lenOfTagOfOneRow = lenOfTagOfOneRow;

  snprintf(command, BUFFER_SIZE,
2768 2769
          "create table if not exists %s.%s (ts timestamp%s) tags %s",
          dbName, superTbl->sTblName, cols, tags);
2770
  if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2771 2772 2773
      errorPrint( "create supertable %s failed!\n\n",
              superTbl->sTblName);
      return -1;
2774 2775
  }
  debugPrint("create supertable %s success!\n\n", superTbl->sTblName);
2776 2777 2778
  return 0;
}

2779
static int createDatabasesAndStables() {
2780 2781 2782 2783
  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) {
2784
    errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL));
2785
    return -1;
2786 2787 2788
  }
  char command[BUFFER_SIZE] = "\0";

2789
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2790 2791
    if (g_Dbs.db[i].drop) {
      sprintf(command, "drop database if exists %s;", g_Dbs.db[i].dbName);
2792
      if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2793 2794 2795 2796
        taos_close(taos);
        return -1;
      }

2797
      int dataLen = 0;
2798
      dataLen += snprintf(command + dataLen,
2799
          BUFFER_SIZE - dataLen, "create database if not exists %s", g_Dbs.db[i].dbName);
2800

2801 2802
      if (g_Dbs.db[i].dbCfg.blocks > 0) {
        dataLen += snprintf(command + dataLen,
2803
            BUFFER_SIZE - dataLen, " blocks %d", g_Dbs.db[i].dbCfg.blocks);
2804 2805 2806
      }
      if (g_Dbs.db[i].dbCfg.cache > 0) {
        dataLen += snprintf(command + dataLen,
2807
            BUFFER_SIZE - dataLen, " cache %d", g_Dbs.db[i].dbCfg.cache);
2808 2809 2810
      }
      if (g_Dbs.db[i].dbCfg.days > 0) {
        dataLen += snprintf(command + dataLen,
2811
            BUFFER_SIZE - dataLen, " days %d", g_Dbs.db[i].dbCfg.days);
2812 2813 2814
      }
      if (g_Dbs.db[i].dbCfg.keep > 0) {
        dataLen += snprintf(command + dataLen,
2815
            BUFFER_SIZE - dataLen, " keep %d", g_Dbs.db[i].dbCfg.keep);
2816 2817 2818
      }
      if (g_Dbs.db[i].dbCfg.quorum > 1) {
        dataLen += snprintf(command + dataLen,
2819
            BUFFER_SIZE - dataLen, " quorum %d", g_Dbs.db[i].dbCfg.quorum);
2820 2821 2822
      }
      if (g_Dbs.db[i].dbCfg.replica > 0) {
        dataLen += snprintf(command + dataLen,
2823
            BUFFER_SIZE - dataLen, " replica %d", g_Dbs.db[i].dbCfg.replica);
2824 2825 2826
      }
      if (g_Dbs.db[i].dbCfg.update > 0) {
        dataLen += snprintf(command + dataLen,
2827
            BUFFER_SIZE - dataLen, " update %d", g_Dbs.db[i].dbCfg.update);
2828 2829 2830 2831 2832 2833 2834
      }
      //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,
2835
            BUFFER_SIZE - dataLen, " minrows %d", g_Dbs.db[i].dbCfg.minRows);
2836 2837 2838
      }
      if (g_Dbs.db[i].dbCfg.maxRows > 0) {
        dataLen += snprintf(command + dataLen,
2839
            BUFFER_SIZE - dataLen, " maxrows %d", g_Dbs.db[i].dbCfg.maxRows);
2840 2841 2842
      }
      if (g_Dbs.db[i].dbCfg.comp > 0) {
        dataLen += snprintf(command + dataLen,
2843
            BUFFER_SIZE - dataLen, " comp %d", g_Dbs.db[i].dbCfg.comp);
2844 2845 2846
      }
      if (g_Dbs.db[i].dbCfg.walLevel > 0) {
        dataLen += snprintf(command + dataLen,
2847
            BUFFER_SIZE - dataLen, " wal %d", g_Dbs.db[i].dbCfg.walLevel);
2848 2849 2850
      }
      if (g_Dbs.db[i].dbCfg.cacheLast > 0) {
        dataLen += snprintf(command + dataLen,
2851
            BUFFER_SIZE - dataLen, " cachelast %d", g_Dbs.db[i].dbCfg.cacheLast);
2852 2853 2854
      }
      if (g_Dbs.db[i].dbCfg.fsync > 0) {
        dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
2855
                " fsync %d", g_Dbs.db[i].dbCfg.fsync);
2856 2857
      }
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", strlen("ms")))
2858 2859
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision,
                      "us", strlen("us")))) {
2860
        dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
2861
                " precision \'%s\';", g_Dbs.db[i].dbCfg.precision);
2862 2863 2864 2865 2866 2867 2868 2869
      }

      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);
2870 2871
    }

2872
    debugPrint("%s() LN%d supertbl count:%"PRIu64"\n",
2873
            __func__, __LINE__, g_Dbs.db[i].superTblCount);
2874 2875 2876

    int validStbCount = 0;

S
Shuduo Sang 已提交
2877
    for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
2878 2879 2880 2881 2882
      sprintf(command, "describe %s.%s;", g_Dbs.db[i].dbName,
              g_Dbs.db[i].superTbls[j].sTblName);
      ret = queryDbExec(taos, command, NO_INSERT_TYPE, true);

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

2886
        if (0 != ret) {
S
Shuduo Sang 已提交
2887
          errorPrint("create super table %"PRIu64" failed!\n\n", j);
2888
          continue;
2889 2890 2891
        }
      }

2892
      ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName,
2893
                &g_Dbs.db[i].superTbls[j]);
2894 2895
      if (0 != ret) {
        errorPrint("\nget super table %s.%s info failed!\n\n",
2896
                g_Dbs.db[i].dbName, g_Dbs.db[i].superTbls[j].sTblName);
2897
        continue;
2898
      }
2899 2900

      validStbCount ++;
2901
    }
2902 2903

    g_Dbs.db[i].superTblCount = validStbCount;
2904 2905 2906 2907 2908 2909
  }

  taos_close(taos);
  return 0;
}

2910 2911
static void* createTable(void *sarg)
{
2912 2913
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
2914

S
Shuduo Sang 已提交
2915
  uint64_t  lastPrintTime = taosGetTimestampMs();
2916

2917
  int buff_len;
2918
  buff_len = BUFFER_SIZE / 8;
2919

2920 2921
  pThreadInfo->buffer = calloc(buff_len, 1);
  if (pThreadInfo->buffer == NULL) {
2922
    errorPrint("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__);
2923 2924
    exit(-1);
  }
2925 2926 2927

  int len = 0;
  int batchNum = 0;
2928

2929
  verbosePrint("%s() LN%d: Creating table from %"PRIu64" to %"PRIu64"\n",
2930 2931
          __func__, __LINE__,
          pThreadInfo->start_table_from, pThreadInfo->end_table_to);
2932

2933
  for (uint64_t i = pThreadInfo->start_table_from;
2934
          i <= pThreadInfo->end_table_to; i++) {
2935
    if (0 == g_Dbs.use_metric) {
2936
      snprintf(pThreadInfo->buffer, buff_len,
2937
              "create table if not exists %s.%s%"PRIu64" %s;",
2938 2939 2940
              pThreadInfo->db_name,
              g_args.tb_prefix, i,
              pThreadInfo->cols);
2941
    } else {
2942 2943
      if (superTblInfo == NULL) {
        errorPrint("%s() LN%d, use metric, but super table info is NULL\n",
2944
                  __func__, __LINE__);
2945
        free(pThreadInfo->buffer);
2946 2947 2948 2949
        exit(-1);
      } else {
        if (0 == len) {
          batchNum = 0;
2950 2951
          memset(pThreadInfo->buffer, 0, buff_len);
          len += snprintf(pThreadInfo->buffer + len,
2952
                  buff_len - len, "create table ");
2953 2954 2955
        }
        char* tagsValBuf = NULL;
        if (0 == superTblInfo->tagSource) {
2956
          tagsValBuf = generateTagVaulesForStb(superTblInfo, i);
2957 2958
        } else {
          tagsValBuf = getTagValueFromTagSample(
2959 2960
                  superTblInfo,
                  i % superTblInfo->tagSampleCount);
2961 2962
        }
        if (NULL == tagsValBuf) {
2963
          free(pThreadInfo->buffer);
2964 2965
          return NULL;
        }
2966
        len += snprintf(pThreadInfo->buffer + len,
2967
                buff_len - len,
2968
                "if not exists %s.%s%"PRIu64" using %s.%s tags %s ",
2969 2970 2971
                pThreadInfo->db_name, superTblInfo->childTblPrefix,
                i, pThreadInfo->db_name,
                superTblInfo->sTblName, tagsValBuf);
2972 2973 2974
        free(tagsValBuf);
        batchNum++;
        if ((batchNum < superTblInfo->batchCreateTableNum)
2975 2976
                && ((buff_len - len)
                    >= (superTblInfo->lenOfTagOfOneRow + 256))) {
2977 2978
          continue;
        }
2979 2980 2981 2982
      }
    }

    len = 0;
2983 2984 2985 2986
    if (0 != queryDbExec(pThreadInfo->taos, pThreadInfo->buffer,
                NO_INSERT_TYPE, false)){
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", pThreadInfo->buffer);
      free(pThreadInfo->buffer);
2987 2988 2989
      return NULL;
    }

S
Shuduo Sang 已提交
2990
    uint64_t  currentPrintTime = taosGetTimestampMs();
2991
    if (currentPrintTime - lastPrintTime > 30*1000) {
2992
      printf("thread[%d] already create %"PRIu64" - %"PRIu64" tables\n",
2993
              pThreadInfo->threadID, pThreadInfo->start_table_from, i);
2994 2995 2996
      lastPrintTime = currentPrintTime;
    }
  }
2997

2998
  if (0 != len) {
2999 3000 3001
    if (0 != queryDbExec(pThreadInfo->taos, pThreadInfo->buffer,
                NO_INSERT_TYPE, false)) {
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", pThreadInfo->buffer);
3002
    }
3003
  }
3004

3005
  free(pThreadInfo->buffer);
3006 3007 3008
  return NULL;
}

3009
static int startMultiThreadCreateChildTable(
3010
        char* cols, int threads, uint64_t tableFrom, int64_t ntables,
3011
        char* db_name, SSuperTable* superTblInfo) {
3012

3013
  pthread_t *pids = malloc(threads * sizeof(pthread_t));
3014
  threadInfo *infos = calloc(1, threads * sizeof(threadInfo));
3015 3016 3017 3018 3019 3020 3021 3022 3023 3024

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

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

S
Shuduo Sang 已提交
3025
  int64_t a = ntables / threads;
3026 3027 3028 3029 3030
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

S
Shuduo Sang 已提交
3031
  int64_t b = 0;
3032
  b = ntables % threads;
3033

3034 3035 3036
  for (int64_t i = 0; i < threads; i++) {
    threadInfo *pThreadInfo = infos + i;
    pThreadInfo->threadID = i;
3037
    tstrncpy(pThreadInfo->db_name, db_name, TSDB_DB_NAME_LEN);
3038
    pThreadInfo->superTblInfo = superTblInfo;
3039
    verbosePrint("%s() %d db_name: %s\n", __func__, __LINE__, db_name);
3040
    pThreadInfo->taos = taos_connect(
3041 3042 3043 3044 3045
            g_Dbs.host,
            g_Dbs.user,
            g_Dbs.password,
            db_name,
            g_Dbs.port);
3046
    if (pThreadInfo->taos == NULL) {
3047
      errorPrint( "%s() LN%d, Failed to connect to TDengine, reason:%s\n",
3048
         __func__, __LINE__, taos_errstr(NULL));
3049
      free(pids);
3050
      free(infos);
3051 3052
      return -1;
    }
3053

3054
    pThreadInfo->start_table_from = tableFrom;
3055
    pThreadInfo->ntables = i<b?a+1:a;
3056 3057
    pThreadInfo->end_table_to = i < b ? tableFrom + a : tableFrom + a - 1;
    tableFrom = pThreadInfo->end_table_to + 1;
3058 3059 3060 3061
    pThreadInfo->use_metric = true;
    pThreadInfo->cols = cols;
    pThreadInfo->minDelay = UINT64_MAX;
    pthread_create(pids + i, NULL, createTable, pThreadInfo);
3062
  }
3063

3064 3065 3066 3067 3068
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

  for (int i = 0; i < threads; i++) {
3069 3070
    threadInfo *pThreadInfo = infos + i;
    taos_close(pThreadInfo->taos);
3071 3072 3073
  }

  free(pids);
3074
  free(infos);
3075 3076

  return 0;
3077 3078
}

3079
static void createChildTables() {
3080 3081
    char tblColsBuf[MAX_SQL_SIZE];
    int len;
3082

3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122
    for (int i = 0; i < g_Dbs.dbCount; i++) {
        if (g_Dbs.use_metric) {
            if (g_Dbs.db[i].superTblCount > 0) {
                // with super table
                for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
                    if ((AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable)
                            || (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists)) {
                        continue;
                    }
                    verbosePrint("%s() LN%d: %s\n", __func__, __LINE__,
                          g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
                    uint64_t startFrom = 0;
                    g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount;

                    verbosePrint("%s() LN%d: create %"PRId64" child tables from %"PRIu64"\n",
                            __func__, __LINE__, g_totalChildTables, startFrom);

                    startMultiThreadCreateChildTable(
                            g_Dbs.db[i].superTbls[j].colsOfCreateChildTable,
                            g_Dbs.threadCountByCreateTbl,
                            startFrom,
                            g_Dbs.db[i].superTbls[j].childTblCount,
                            g_Dbs.db[i].dbName, &(g_Dbs.db[i].superTbls[j]));
                }
            }
        } else {
            // normal table
            len = snprintf(tblColsBuf, MAX_SQL_SIZE, "(TS TIMESTAMP");
            for (int j = 0; j < g_args.num_of_CPR; j++) {
                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);
            }
3123

3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135
            snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ")");

            verbosePrint("%s() LN%d: dbName: %s num of tb: %"PRId64" schema: %s\n",
                    __func__, __LINE__,
                    g_Dbs.db[i].dbName, g_args.num_of_tables, tblColsBuf);
            startMultiThreadCreateChildTable(
                    tblColsBuf,
                    g_Dbs.threadCountByCreateTbl,
                    0,
                    g_args.num_of_tables,
                    g_Dbs.db[i].dbName,
                    NULL);
3136
        }
3137
    }
3138 3139 3140 3141 3142
}

/*
  Read 10000 lines at most. If more than 10000 lines, continue to read after using
*/
3143
static int readTagFromCsvFileToMem(SSuperTable  * superTblInfo) {
3144 3145 3146
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
3147

3148 3149
  FILE *fp = fopen(superTblInfo->tagsFile, "r");
  if (fp == NULL) {
3150
    printf("Failed to open tags file: %s, reason:%s\n",
3151
            superTblInfo->tagsFile, strerror(errno));
3152 3153 3154 3155 3156 3157 3158
    return -1;
  }

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

3160 3161 3162 3163 3164 3165 3166 3167 3168
  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;
  }

3169
  while((readLen = tgetline(&line, &n, fp)) != -1) {
3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181
    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) {
3182
      char *tmp = realloc(tagDataBuf,
3183
              (size_t)tagCount*1.5*superTblInfo->lenOfTagOfOneRow);
3184 3185 3186
      if (tmp != NULL) {
        tagDataBuf = tmp;
        tagCount = (int)(tagCount*1.5);
3187
        memset(tagDataBuf + count*superTblInfo->lenOfTagOfOneRow,
3188
                0, (size_t)((tagCount-count)*superTblInfo->lenOfTagOfOneRow));
3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207
      } 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;
}

3208
#if 0
3209 3210 3211 3212
int readSampleFromJsonFileToMem(SSuperTable  * superTblInfo) {
  // TODO
  return 0;
}
3213
#endif
3214 3215 3216 3217

/*
  Read 10000 lines at most. If more than 10000 lines, continue to read after using
*/
3218
static int readSampleFromCsvFileToMem(
3219
        SSuperTable* superTblInfo) {
3220 3221 3222 3223
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
  int getRows = 0;
3224

3225 3226
  FILE*  fp = fopen(superTblInfo->sampleFile, "r");
  if (fp == NULL) {
3227 3228 3229
      errorPrint( "Failed to open sample file: %s, reason:%s\n",
              superTblInfo->sampleFile, strerror(errno));
      return -1;
3230
  }
3231

3232
  assert(superTblInfo->sampleDataBuf);
3233
  memset(superTblInfo->sampleDataBuf, 0,
3234
          MAX_SAMPLES_ONCE_FROM_FILE * superTblInfo->lenOfOneRow);
3235
  while(1) {
3236
    readLen = tgetline(&line, &n, fp);
3237 3238
    if (-1 == readLen) {
      if(0 != fseek(fp, 0, SEEK_SET)) {
3239
        errorPrint( "Failed to fseek file: %s, reason:%s\n",
3240
                superTblInfo->sampleFile, strerror(errno));
3241
        fclose(fp);
3242 3243 3244 3245
        return -1;
      }
      continue;
    }
3246

3247 3248 3249 3250 3251 3252 3253 3254 3255
    if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
      line[--readLen] = 0;
    }

    if (readLen == 0) {
      continue;
    }

    if (readLen > superTblInfo->lenOfOneRow) {
3256
      printf("sample row len[%d] overflow define schema len[%"PRIu64"], so discard this row\n",
3257
              (int32_t)readLen, superTblInfo->lenOfOneRow);
3258 3259 3260
      continue;
    }

3261
    memcpy(superTblInfo->sampleDataBuf + getRows * superTblInfo->lenOfOneRow,
3262
          line, readLen);
3263 3264 3265 3266 3267 3268 3269
    getRows++;

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

3270
  fclose(fp);
3271 3272 3273 3274
  tmfree(line);
  return 0;
}

3275
static bool getColumnAndTagTypeFromInsertJsonFile(
3276
        cJSON* stbInfo, SSuperTable* superTbls) {
3277
  bool  ret = false;
3278

3279
  // columns
3280 3281
  cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns");
  if (columns && columns->type != cJSON_Array) {
3282
    printf("ERROR: failed to read json, columns not found\n");
3283 3284 3285 3286 3287 3288
    goto PARSE_OVER;
  } else if (NULL == columns) {
    superTbls->columnCount = 0;
    superTbls->tagCount    = 0;
    return true;
  }
3289

3290
  int columnSize = cJSON_GetArraySize(columns);
3291
  if ((columnSize + 1/* ts */) > MAX_COLUMN_COUNT) {
3292
    errorPrint("%s() LN%d, failed to read json, column size overflow, max column size is %d\n",
3293
            __func__, __LINE__, MAX_COLUMN_COUNT);
3294 3295 3296 3297 3298 3299
    goto PARSE_OVER;
  }

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

3301
  //superTbls->columnCount = columnSize;
3302 3303 3304 3305 3306 3307 3308
  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) {
3309
      count = countObj->valueint;
3310
    } else if (countObj && countObj->type != cJSON_Number) {
3311
      errorPrint("%s() LN%d, failed to read json, column count not found\n",
3312
          __func__, __LINE__);
3313 3314 3315 3316 3317
      goto PARSE_OVER;
    } else {
      count = 1;
    }

3318
    // column info
3319 3320
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(column, "type");
3321 3322 3323
    if (!dataType || dataType->type != cJSON_String
        || dataType->valuestring == NULL) {
      errorPrint("%s() LN%d: failed to read json, column type not found\n",
3324
          __func__, __LINE__);
3325 3326
      goto PARSE_OVER;
    }
3327
    //tstrncpy(superTbls->columns[k].dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
3328
    tstrncpy(columnCase.dataType, dataType->valuestring, strlen(dataType->valuestring) + 1);
3329

3330 3331
    cJSON* dataLen = cJSON_GetObjectItem(column, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3332
      columnCase.dataLen = dataLen->valueint;
3333
    } else if (dataLen && dataLen->type != cJSON_Number) {
3334
      debugPrint("%s() LN%d: failed to read json, column len not found\n",
3335
          __func__, __LINE__);
3336 3337 3338 3339
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 8;
    }
3340

3341
    for (int n = 0; n < count; ++n) {
3342
      tstrncpy(superTbls->columns[index].dataType,
3343
              columnCase.dataType, strlen(columnCase.dataType) + 1);
3344
      superTbls->columns[index].dataLen = columnCase.dataLen;
3345 3346
      index++;
    }
3347
  }
3348

3349 3350
  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",
3351
            __func__, __LINE__, MAX_COLUMN_COUNT);
3352 3353 3354
    goto PARSE_OVER;
  }

3355
  superTbls->columnCount = index;
3356

3357 3358
  count = 1;
  index = 0;
3359
  // tags
3360 3361
  cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags");
  if (!tags || tags->type != cJSON_Array) {
3362
    errorPrint("%s() LN%d, failed to read json, tags not found\n",
3363
        __func__, __LINE__);
3364 3365
    goto PARSE_OVER;
  }
3366

3367 3368
  int tagSize = cJSON_GetArraySize(tags);
  if (tagSize > MAX_TAG_COUNT) {
3369
    errorPrint("%s() LN%d, failed to read json, tags size overflow, max tag size is %d\n",
3370
        __func__, __LINE__, MAX_TAG_COUNT);
3371 3372
    goto PARSE_OVER;
  }
3373 3374

  //superTbls->tagCount = tagSize;
3375 3376 3377
  for (int k = 0; k < tagSize; ++k) {
    cJSON* tag = cJSON_GetArrayItem(tags, k);
    if (tag == NULL) continue;
3378

3379 3380 3381
    count = 1;
    cJSON* countObj = cJSON_GetObjectItem(tag, "count");
    if (countObj && countObj->type == cJSON_Number) {
3382
      count = countObj->valueint;
3383
    } else if (countObj && countObj->type != cJSON_Number) {
3384
      printf("ERROR: failed to read json, column count not found\n");
3385 3386 3387 3388 3389
      goto PARSE_OVER;
    } else {
      count = 1;
    }

3390
    // column info
3391 3392
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(tag, "type");
3393 3394 3395
    if (!dataType || dataType->type != cJSON_String
        || dataType->valuestring == NULL) {
      errorPrint("%s() LN%d, failed to read json, tag type not found\n",
3396
          __func__, __LINE__);
3397 3398
      goto PARSE_OVER;
    }
3399
    tstrncpy(columnCase.dataType, dataType->valuestring, strlen(dataType->valuestring) + 1);
3400

3401 3402
    cJSON* dataLen = cJSON_GetObjectItem(tag, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3403
      columnCase.dataLen = dataLen->valueint;
3404
    } else if (dataLen && dataLen->type != cJSON_Number) {
3405
      errorPrint("%s() LN%d, failed to read json, column len not found\n",
3406
          __func__, __LINE__);
3407 3408 3409
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 0;
3410 3411
    }

3412
    for (int n = 0; n < count; ++n) {
3413
      tstrncpy(superTbls->tags[index].dataType, columnCase.dataType,
3414
          strlen(columnCase.dataType) + 1);
3415
      superTbls->tags[index].dataLen = columnCase.dataLen;
3416 3417
      index++;
    }
3418
  }
3419 3420

  if (index > MAX_TAG_COUNT) {
3421
    errorPrint("%s() LN%d, failed to read json, tags size overflow, allowed max tag count is %d\n",
3422
        __func__, __LINE__, MAX_TAG_COUNT);
3423 3424 3425
    goto PARSE_OVER;
  }

3426 3427
  superTbls->tagCount = index;

3428 3429
  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",
3430
        __func__, __LINE__, MAX_COLUMN_COUNT);
3431 3432
    goto PARSE_OVER;
  }
3433 3434
  ret = true;

3435
PARSE_OVER:
3436 3437 3438 3439 3440 3441 3442 3443
  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) {
3444
    tstrncpy(g_Dbs.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3445 3446 3447 3448
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
3449
    tstrncpy(g_Dbs.host, host->valuestring, MAX_HOSTNAME_SIZE);
3450
  } else if (!host) {
3451
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
3452
  } else {
3453
    printf("ERROR: failed to read json, host not found\n");
3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465
    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) {
3466
    tstrncpy(g_Dbs.user, user->valuestring, MAX_USERNAME_SIZE);
3467
  } else if (!user) {
3468
    tstrncpy(g_Dbs.user, "root", MAX_USERNAME_SIZE);
3469 3470 3471 3472
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
3473
    tstrncpy(g_Dbs.password, password->valuestring, MAX_PASSWORD_SIZE);
3474
  } else if (!password) {
3475
    tstrncpy(g_Dbs.password, "taosdata", MAX_PASSWORD_SIZE);
3476 3477 3478 3479
  }

  cJSON* resultfile = cJSON_GetObjectItem(root, "result_file");
  if (resultfile && resultfile->type == cJSON_String && resultfile->valuestring != NULL) {
3480
    tstrncpy(g_Dbs.resultFile, resultfile->valuestring, MAX_FILE_NAME_LEN);
3481
  } else if (!resultfile) {
3482
    tstrncpy(g_Dbs.resultFile, "./insert_res.txt", MAX_FILE_NAME_LEN);
3483 3484 3485 3486 3487 3488 3489 3490
  }

  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 {
3491
    printf("ERROR: failed to read json, threads not found\n");
3492
    goto PARSE_OVER;
3493 3494
  }

3495 3496 3497 3498
  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 已提交
3499
    g_Dbs.threadCountByCreateTbl = 1;
3500
  } else {
3501
    errorPrint("%s() LN%d, failed to read json, threads2 not found\n",
3502
            __func__, __LINE__);
3503
    goto PARSE_OVER;
3504
  }
3505

3506 3507
  cJSON* gInsertInterval = cJSON_GetObjectItem(root, "insert_interval");
  if (gInsertInterval && gInsertInterval->type == cJSON_Number) {
3508 3509 3510 3511 3512
    if (gInsertInterval->valueint <0) {
      errorPrint("%s() LN%d, failed to read json, insert interval input mistake\n",
            __func__, __LINE__);
      goto PARSE_OVER;
    }
3513 3514 3515 3516
    g_args.insert_interval = gInsertInterval->valueint;
  } else if (!gInsertInterval) {
    g_args.insert_interval = 0;
  } else {
3517
    errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
3518
        __func__, __LINE__);
3519 3520
    goto PARSE_OVER;
  }
3521

3522 3523
  cJSON* interlaceRows = cJSON_GetObjectItem(root, "interlace_rows");
  if (interlaceRows && interlaceRows->type == cJSON_Number) {
3524 3525 3526 3527 3528 3529
    if (interlaceRows->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;

    }
3530 3531
    g_args.interlace_rows = interlaceRows->valueint;
  } else if (!interlaceRows) {
3532
    g_args.interlace_rows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
3533
  } else {
3534
    errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
3535
        __func__, __LINE__);
3536
    goto PARSE_OVER;
3537
  }
3538

3539 3540
  cJSON* maxSqlLen = cJSON_GetObjectItem(root, "max_sql_len");
  if (maxSqlLen && maxSqlLen->type == cJSON_Number) {
3541 3542 3543 3544 3545
    if (maxSqlLen->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;
    }
3546 3547
    g_args.max_sql_len = maxSqlLen->valueint;
  } else if (!maxSqlLen) {
sangshuduo's avatar
sangshuduo 已提交
3548
    g_args.max_sql_len = (1024*1024);
3549
  } else {
3550
    errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
3551
        __func__, __LINE__);
3552 3553 3554 3555 3556
    goto PARSE_OVER;
  }

  cJSON* numRecPerReq = cJSON_GetObjectItem(root, "num_of_records_per_req");
  if (numRecPerReq && numRecPerReq->type == cJSON_Number) {
3557
    if (numRecPerReq->valueint <= 0) {
3558 3559 3560
      errorPrint("%s() LN%d, failed to read json, num_of_records_per_req input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;
3561
    } else if (numRecPerReq->valueint > MAX_RECORDS_PER_REQ) {
3562 3563 3564 3565 3566
      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();
3567
      numRecPerReq->valueint = MAX_RECORDS_PER_REQ;
3568
    }
3569 3570
    g_args.num_of_RPR = numRecPerReq->valueint;
  } else if (!numRecPerReq) {
3571
    g_args.num_of_RPR = MAX_RECORDS_PER_REQ;
3572
  } else {
3573
    errorPrint("%s() LN%d, failed to read json, num_of_records_per_req not found\n",
3574
        __func__, __LINE__);
3575 3576 3577
    goto PARSE_OVER;
  }

3578
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
3579
  if (answerPrompt
3580 3581
          && answerPrompt->type == cJSON_String
          && answerPrompt->valuestring != NULL) {
3582 3583 3584 3585 3586 3587 3588 3589
    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) {
3590
    g_args.answer_yes = true;   // default is no, mean answer_yes.
3591
  } else {
3592
    errorPrint("%s", "failed to read json, confirm_parameter_prompt input mistake\n");
3593
    goto PARSE_OVER;
3594
  }
3595

3596 3597
  // rows per table need be less than insert batch
  if (g_args.interlace_rows > g_args.num_of_RPR) {
3598
      printf("NOTICE: interlace rows value %u > num_of_records_per_req %u\n\n",
3599
              g_args.interlace_rows, g_args.num_of_RPR);
3600
      printf("        interlace rows value will be set to num_of_records_per_req %u\n\n",
3601 3602 3603 3604 3605
              g_args.num_of_RPR);
      prompt();
      g_args.interlace_rows = g_args.num_of_RPR;
  }

3606 3607
  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (!dbs || dbs->type != cJSON_Array) {
3608
    printf("ERROR: failed to read json, databases not found\n");
3609 3610 3611 3612 3613
    goto PARSE_OVER;
  }

  int dbSize = cJSON_GetArraySize(dbs);
  if (dbSize > MAX_DB_COUNT) {
3614
    errorPrint(
3615 3616
            "ERROR: failed to read json, databases size overflow, max database is %d\n",
            MAX_DB_COUNT);
3617 3618 3619 3620 3621 3622 3623 3624
    goto PARSE_OVER;
  }

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

3625
    // dbinfo
3626 3627
    cJSON *dbinfo = cJSON_GetObjectItem(dbinfos, "dbinfo");
    if (!dbinfo || dbinfo->type != cJSON_Object) {
3628
      printf("ERROR: failed to read json, dbinfo not found\n");
3629 3630
      goto PARSE_OVER;
    }
3631

3632 3633
    cJSON *dbName = cJSON_GetObjectItem(dbinfo, "name");
    if (!dbName || dbName->type != cJSON_String || dbName->valuestring == NULL) {
3634
      printf("ERROR: failed to read json, db name not found\n");
3635 3636
      goto PARSE_OVER;
    }
3637
    tstrncpy(g_Dbs.db[i].dbName, dbName->valuestring, TSDB_DB_NAME_LEN);
3638 3639 3640

    cJSON *drop = cJSON_GetObjectItem(dbinfo, "drop");
    if (drop && drop->type == cJSON_String && drop->valuestring != NULL) {
3641 3642
      if (0 == strncasecmp(drop->valuestring, "yes", strlen("yes"))) {
        g_Dbs.db[i].drop = true;
3643
      } else {
3644
        g_Dbs.db[i].drop = false;
3645
      }
3646
    } else if (!drop) {
3647
      g_Dbs.db[i].drop = g_args.drop_database;
3648
    } else {
3649
      errorPrint("%s() LN%d, failed to read json, drop input mistake\n",
3650
              __func__, __LINE__);
3651 3652 3653 3654
      goto PARSE_OVER;
    }

    cJSON *precision = cJSON_GetObjectItem(dbinfo, "precision");
3655
    if (precision && precision->type == cJSON_String
3656
            && precision->valuestring != NULL) {
3657
      tstrncpy(g_Dbs.db[i].dbCfg.precision, precision->valuestring,
3658
              8);
3659
    } else if (!precision) {
3660
      memset(g_Dbs.db[i].dbCfg.precision, 0, 8);
3661
    } else {
3662
      printf("ERROR: failed to read json, precision not found\n");
3663 3664 3665 3666 3667 3668 3669 3670 3671
      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 {
3672
      printf("ERROR: failed to read json, update not found\n");
3673 3674 3675 3676 3677 3678 3679 3680 3681
      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 {
3682
      printf("ERROR: failed to read json, replica not found\n");
3683 3684 3685 3686 3687 3688 3689 3690 3691
      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 {
3692 3693
     printf("ERROR: failed to read json, keep not found\n");
     goto PARSE_OVER;
3694
    }
3695

3696 3697 3698 3699 3700 3701
    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 {
3702 3703
     printf("ERROR: failed to read json, days not found\n");
     goto PARSE_OVER;
3704
    }
3705

3706 3707 3708 3709 3710 3711
    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 {
3712 3713
     printf("ERROR: failed to read json, cache not found\n");
     goto PARSE_OVER;
3714
    }
3715

3716 3717 3718 3719 3720 3721
    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 {
3722 3723
     printf("ERROR: failed to read json, block not found\n");
     goto PARSE_OVER;
3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739
    }

    //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) {
3740
      g_Dbs.db[i].dbCfg.minRows = 0;    // 0 means default
3741
    } else {
3742 3743
     printf("ERROR: failed to read json, minRows not found\n");
     goto PARSE_OVER;
3744 3745 3746 3747 3748 3749
    }

    cJSON* maxRows= cJSON_GetObjectItem(dbinfo, "maxRows");
    if (maxRows && maxRows->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.maxRows = maxRows->valueint;
    } else if (!maxRows) {
3750
      g_Dbs.db[i].dbCfg.maxRows = 0;    // 0 means default
3751
    } else {
3752 3753
     printf("ERROR: failed to read json, maxRows not found\n");
     goto PARSE_OVER;
3754 3755 3756 3757 3758 3759 3760 3761
    }

    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 {
3762 3763
     printf("ERROR: failed to read json, comp not found\n");
     goto PARSE_OVER;
3764 3765 3766 3767 3768 3769 3770 3771
    }

    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 {
3772 3773
     printf("ERROR: failed to read json, walLevel not found\n");
     goto PARSE_OVER;
3774 3775
    }

3776 3777 3778 3779 3780 3781
    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 {
3782 3783
     printf("ERROR: failed to read json, cacheLast not found\n");
     goto PARSE_OVER;
3784 3785
    }

3786 3787 3788 3789
    cJSON* quorum= cJSON_GetObjectItem(dbinfo, "quorum");
    if (quorum && quorum->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.quorum = quorum->valueint;
    } else if (!quorum) {
3790
      g_Dbs.db[i].dbCfg.quorum = 1;
3791
    } else {
3792 3793
     printf("failed to read json, quorum input mistake");
     goto PARSE_OVER;
3794 3795 3796 3797 3798 3799 3800 3801
    }

    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 {
3802
      errorPrint("%s() LN%d, failed to read json, fsync input mistake\n",
3803
              __func__, __LINE__);
3804
      goto PARSE_OVER;
3805
    }
3806

3807
    // super_talbes
3808 3809
    cJSON *stables = cJSON_GetObjectItem(dbinfos, "super_tables");
    if (!stables || stables->type != cJSON_Array) {
3810
      errorPrint("%s() LN%d, failed to read json, super_tables not found\n",
3811
              __func__, __LINE__);
3812
      goto PARSE_OVER;
3813 3814
    }

3815 3816
    int stbSize = cJSON_GetArraySize(stables);
    if (stbSize > MAX_SUPER_TABLE_COUNT) {
3817
      errorPrint(
3818 3819
              "%s() LN%d, failed to read json, supertable size overflow, max supertable is %d\n",
              __func__, __LINE__, MAX_SUPER_TABLE_COUNT);
3820 3821 3822 3823 3824 3825 3826
      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;
3827 3828

      // dbinfo
3829
      cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name");
3830 3831
      if (!stbName || stbName->type != cJSON_String
              || stbName->valuestring == NULL) {
3832
        errorPrint("%s() LN%d, failed to read json, stb name not found\n",
3833
                __func__, __LINE__);
3834 3835
        goto PARSE_OVER;
      }
3836
      tstrncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring,
3837
              TSDB_TABLE_NAME_LEN);
3838

3839 3840
      cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix");
      if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) {
3841
        printf("ERROR: failed to read json, childtable_prefix not found\n");
3842 3843
        goto PARSE_OVER;
      }
3844
      tstrncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring,
3845
              TSDB_TABLE_NAME_LEN - 20);
3846

3847
      cJSON *autoCreateTbl = cJSON_GetObjectItem(stbInfo, "auto_create_table");
3848
      if (autoCreateTbl
3849 3850
              && autoCreateTbl->type == cJSON_String
              && autoCreateTbl->valuestring != NULL) {
3851 3852 3853 3854 3855 3856 3857 3858
          if ((0 == strncasecmp(autoCreateTbl->valuestring, "yes", 3))
                  && (TBL_ALREADY_EXISTS != g_Dbs.db[i].superTbls[j].childTblExists)) {
              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;
          }
3859
      } else if (!autoCreateTbl) {
3860
          g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL;
3861
      } else {
3862 3863
          printf("ERROR: failed to read json, auto_create_table not found\n");
          goto PARSE_OVER;
3864
      }
3865

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

      cJSON *childTblExists = cJSON_GetObjectItem(stbInfo, "child_table_exists"); // yes, no
3877
      if (childTblExists
3878 3879
              && childTblExists->type == cJSON_String
              && childTblExists->valuestring != NULL) {
3880 3881
        if ((0 == strncasecmp(childTblExists->valuestring, "yes", 3))
            && (g_Dbs.db[i].drop == false)) {
3882
          g_Dbs.db[i].superTbls[j].childTblExists = TBL_ALREADY_EXISTS;
3883
        } else if ((0 == strncasecmp(childTblExists->valuestring, "no", 2)
3884
              || (g_Dbs.db[i].drop == true))) {
3885 3886 3887 3888 3889 3890 3891
          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 {
3892
        errorPrint("%s() LN%d, failed to read json, child_table_exists not found\n",
3893
                __func__, __LINE__);
3894 3895
        goto PARSE_OVER;
      }
3896

3897 3898 3899 3900
      if (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
          g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL;
      }

3901 3902
      cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count");
      if (!count || count->type != cJSON_Number || 0 >= count->valueint) {
3903
        errorPrint("%s() LN%d, failed to read json, childtable_count input mistake\n",
3904
                __func__, __LINE__);
3905 3906 3907 3908 3909
        goto PARSE_OVER;
      }
      g_Dbs.db[i].superTbls[j].childTblCount = count->valueint;

      cJSON *dataSource = cJSON_GetObjectItem(stbInfo, "data_source");
3910
      if (dataSource && dataSource->type == cJSON_String
3911
              && dataSource->valuestring != NULL) {
3912
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource,
3913
                dataSource->valuestring, TSDB_DB_NAME_LEN);
3914
      } else if (!dataSource) {
3915
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource, "rand", TSDB_DB_NAME_LEN);
3916
      } else {
3917
        errorPrint("%s() LN%d, failed to read json, data_source not found\n",
3918
            __func__, __LINE__);
3919 3920 3921
        goto PARSE_OVER;
      }

3922 3923 3924 3925 3926 3927 3928
      cJSON *stbIface = cJSON_GetObjectItem(stbInfo, "insert_mode"); // taosc , rest, stmt
      if (stbIface && stbIface->type == cJSON_String
              && stbIface->valuestring != NULL) {
        if (0 == strcasecmp(stbIface->valuestring, "taosc")) {
            g_Dbs.db[i].superTbls[j].iface= TAOSC_IFACE;
        } else if (0 == strcasecmp(stbIface->valuestring, "rest")) {
            g_Dbs.db[i].superTbls[j].iface= REST_IFACE;
3929
#if STMT_IFACE_ENABLED == 1
3930 3931
        } else if (0 == strcasecmp(stbIface->valuestring, "stmt")) {
            g_Dbs.db[i].superTbls[j].iface= STMT_IFACE;
3932
#endif
3933 3934
        } else {
            errorPrint("%s() LN%d, failed to read json, insert_mode %s not recognized\n",
3935
                    __func__, __LINE__, stbIface->valuestring);
3936 3937
            goto PARSE_OVER;
        }
3938 3939
      } else if (!stbIface) {
        g_Dbs.db[i].superTbls[j].iface = TAOSC_IFACE;
3940
      } else {
3941
        errorPrint("%s", "failed to read json, insert_mode not found\n");
3942 3943 3944
        goto PARSE_OVER;
      }

3945
      cJSON* childTbl_limit = cJSON_GetObjectItem(stbInfo, "childtable_limit");
3946 3947
      if ((childTbl_limit) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
3948
        if (childTbl_limit->type != cJSON_Number) {
3949 3950
            printf("ERROR: failed to read json, childtable_limit\n");
            goto PARSE_OVER;
3951 3952 3953
        }
        g_Dbs.db[i].superTbls[j].childTblLimit = childTbl_limit->valueint;
      } else {
3954
        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.
3955 3956 3957
      }

      cJSON* childTbl_offset = cJSON_GetObjectItem(stbInfo, "childtable_offset");
3958 3959
      if ((childTbl_offset) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
3960 3961
        if ((childTbl_offset->type != cJSON_Number)
                || (0 > childTbl_offset->valueint)) {
3962 3963
            printf("ERROR: failed to read json, childtable_offset\n");
            goto PARSE_OVER;
3964 3965 3966 3967 3968 3969
        }
        g_Dbs.db[i].superTbls[j].childTblOffset = childTbl_offset->valueint;
      } else {
        g_Dbs.db[i].superTbls[j].childTblOffset = 0;
      }

3970 3971
      cJSON *ts = cJSON_GetObjectItem(stbInfo, "start_timestamp");
      if (ts && ts->type == cJSON_String && ts->valuestring != NULL) {
3972
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
3973
                ts->valuestring, TSDB_DB_NAME_LEN);
3974
      } else if (!ts) {
3975
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
3976
                "now", TSDB_DB_NAME_LEN);
3977
      } else {
3978
        printf("ERROR: failed to read json, start_timestamp not found\n");
3979 3980
        goto PARSE_OVER;
      }
3981

3982 3983 3984 3985
      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) {
3986
        g_Dbs.db[i].superTbls[j].timeStampStep = DEFAULT_TIMESTAMP_STEP;
3987
      } else {
3988
        printf("ERROR: failed to read json, timestamp_step not found\n");
3989 3990 3991 3992
        goto PARSE_OVER;
      }

      cJSON *sampleFormat = cJSON_GetObjectItem(stbInfo, "sample_format");
3993
      if (sampleFormat && sampleFormat->type
3994
              == cJSON_String && sampleFormat->valuestring != NULL) {
3995
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat,
3996
                sampleFormat->valuestring, TSDB_DB_NAME_LEN);
3997
      } else if (!sampleFormat) {
3998
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat, "csv", TSDB_DB_NAME_LEN);
3999
      } else {
4000
        printf("ERROR: failed to read json, sample_format not found\n");
4001
        goto PARSE_OVER;
4002
      }
4003

4004
      cJSON *sampleFile = cJSON_GetObjectItem(stbInfo, "sample_file");
4005 4006
      if (sampleFile && sampleFile->type == cJSON_String
          && sampleFile->valuestring != NULL) {
4007
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFile,
4008
                sampleFile->valuestring, MAX_FILE_NAME_LEN);
4009 4010 4011
      } else if (!sampleFile) {
        memset(g_Dbs.db[i].superTbls[j].sampleFile, 0, MAX_FILE_NAME_LEN);
      } else {
4012
        printf("ERROR: failed to read json, sample_file not found\n");
4013
        goto PARSE_OVER;
4014
      }
4015

4016
      cJSON *tagsFile = cJSON_GetObjectItem(stbInfo, "tags_file");
4017 4018
      if ((tagsFile && tagsFile->type == cJSON_String)
              && (tagsFile->valuestring != NULL)) {
4019
        tstrncpy(g_Dbs.db[i].superTbls[j].tagsFile,
4020
                tagsFile->valuestring, MAX_FILE_NAME_LEN);
4021 4022 4023 4024 4025 4026 4027 4028 4029
        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 {
4030
        printf("ERROR: failed to read json, tags_file not found\n");
4031 4032
        goto PARSE_OVER;
      }
4033

sangshuduo's avatar
sangshuduo 已提交
4034 4035 4036
      cJSON* stbMaxSqlLen = cJSON_GetObjectItem(stbInfo, "max_sql_len");
      if (stbMaxSqlLen && stbMaxSqlLen->type == cJSON_Number) {
        int32_t len = stbMaxSqlLen->valueint;
4037 4038
        if (len > TSDB_MAX_ALLOWED_SQL_LEN) {
          len = TSDB_MAX_ALLOWED_SQL_LEN;
4039 4040
        } else if (len < 5) {
          len = 5;
4041
        }
4042 4043
        g_Dbs.db[i].superTbls[j].maxSqlLen = len;
      } else if (!maxSqlLen) {
4044
        g_Dbs.db[i].superTbls[j].maxSqlLen = g_args.max_sql_len;
4045
      } else {
sangshuduo's avatar
sangshuduo 已提交
4046
        errorPrint("%s() LN%d, failed to read json, stbMaxSqlLen input mistake\n",
4047
            __func__, __LINE__);
4048
        goto PARSE_OVER;
4049
      }
4050
/*
4051 4052 4053 4054 4055
      cJSON *multiThreadWriteOneTbl =
          cJSON_GetObjectItem(stbInfo, "multi_thread_write_one_tbl"); // no , yes
      if (multiThreadWriteOneTbl
              && multiThreadWriteOneTbl->type == cJSON_String
              && multiThreadWriteOneTbl->valuestring != NULL) {
4056 4057 4058 4059
        if (0 == strncasecmp(multiThreadWriteOneTbl->valuestring, "yes", 3)) {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 1;
        } else {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
4060
        }
4061 4062 4063
      } else if (!multiThreadWriteOneTbl) {
        g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
      } else {
4064
        printf("ERROR: failed to read json, multiThreadWriteOneTbl not found\n");
4065 4066
        goto PARSE_OVER;
      }
4067
*/
sangshuduo's avatar
sangshuduo 已提交
4068 4069 4070
      cJSON* stbInterlaceRows = cJSON_GetObjectItem(stbInfo, "interlace_rows");
      if (stbInterlaceRows && stbInterlaceRows->type == cJSON_Number) {
        if (stbInterlaceRows->valueint < 0) {
4071 4072 4073 4074
          errorPrint("%s() LN%d, failed to read json, interlace rows input mistake\n",
            __func__, __LINE__);
          goto PARSE_OVER;
        }
sangshuduo's avatar
sangshuduo 已提交
4075
        g_Dbs.db[i].superTbls[j].interlaceRows = stbInterlaceRows->valueint;
4076 4077
        // rows per table need be less than insert batch
        if (g_Dbs.db[i].superTbls[j].interlaceRows > g_args.num_of_RPR) {
4078
          printf("NOTICE: db[%d].superTbl[%d]'s interlace rows value %u > num_of_records_per_req %u\n\n",
4079 4080
                  i, j, g_Dbs.db[i].superTbls[j].interlaceRows,
                  g_args.num_of_RPR);
4081
          printf("        interlace rows value will be set to num_of_records_per_req %u\n\n",
4082
                  g_args.num_of_RPR);
4083
          prompt();
4084 4085
          g_Dbs.db[i].superTbls[j].interlaceRows = g_args.num_of_RPR;
        }
sangshuduo's avatar
sangshuduo 已提交
4086
      } else if (!stbInterlaceRows) {
4087
        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
4088
      } else {
4089
        errorPrint(
4090 4091
                "%s() LN%d, failed to read json, interlace rows input mistake\n",
                __func__, __LINE__);
4092
        goto PARSE_OVER;
4093
      }
4094 4095 4096

      cJSON* disorderRatio = cJSON_GetObjectItem(stbInfo, "disorder_ratio");
      if (disorderRatio && disorderRatio->type == cJSON_Number) {
4097 4098 4099 4100 4101 4102
        if (disorderRatio->valueint > 50)
          disorderRatio->valueint = 50;

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

4103 4104 4105 4106
        g_Dbs.db[i].superTbls[j].disorderRatio = disorderRatio->valueint;
      } else if (!disorderRatio) {
        g_Dbs.db[i].superTbls[j].disorderRatio = 0;
      } else {
4107
        printf("ERROR: failed to read json, disorderRatio not found\n");
4108
        goto PARSE_OVER;
4109
      }
4110 4111 4112 4113 4114 4115 4116

      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 {
4117
        printf("ERROR: failed to read json, disorderRange not found\n");
4118 4119
        goto PARSE_OVER;
      }
4120

4121 4122
      cJSON* insertRows = cJSON_GetObjectItem(stbInfo, "insert_rows");
      if (insertRows && insertRows->type == cJSON_Number) {
4123 4124 4125 4126 4127
        if (insertRows->valueint < 0) {
          errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n",
                __func__, __LINE__);
          goto PARSE_OVER;
        }
4128 4129 4130 4131
        g_Dbs.db[i].superTbls[j].insertRows = insertRows->valueint;
      } else if (!insertRows) {
        g_Dbs.db[i].superTbls[j].insertRows = 0x7FFFFFFFFFFFFFFF;
      } else {
4132
        errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n",
4133
                __func__, __LINE__);
4134 4135 4136 4137 4138 4139
        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;
4140 4141 4142 4143 4144
        if (insertInterval->valueint < 0) {
          errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
                __func__, __LINE__);
          goto PARSE_OVER;
        }
4145
      } else if (!insertInterval) {
4146
        verbosePrint("%s() LN%d: stable insert interval be overrided by global %"PRIu64".\n",
4147
                __func__, __LINE__, g_args.insert_interval);
4148 4149
        g_Dbs.db[i].superTbls[j].insertInterval = g_args.insert_interval;
      } else {
4150
        errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
4151
                __func__, __LINE__);
4152 4153 4154
        goto PARSE_OVER;
      }

4155
      int retVal = getColumnAndTagTypeFromInsertJsonFile(
4156
              stbInfo, &g_Dbs.db[i].superTbls[j]);
4157 4158
      if (false == retVal) {
        goto PARSE_OVER;
4159 4160
      }
    }
4161 4162 4163 4164
  }

  ret = true;

4165
PARSE_OVER:
4166 4167 4168 4169 4170 4171 4172 4173
  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) {
4174
    tstrncpy(g_queryInfo.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
4175 4176 4177 4178
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
4179
    tstrncpy(g_queryInfo.host, host->valuestring, MAX_HOSTNAME_SIZE);
4180
  } else if (!host) {
4181
    tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
4182
  } else {
4183
    printf("ERROR: failed to read json, host not found\n");
4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195
    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) {
4196
    tstrncpy(g_queryInfo.user, user->valuestring, MAX_USERNAME_SIZE);
4197
  } else if (!user) {
4198
    tstrncpy(g_queryInfo.user, "root", MAX_USERNAME_SIZE); ;
4199 4200 4201 4202
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
4203
    tstrncpy(g_queryInfo.password, password->valuestring, MAX_PASSWORD_SIZE);
4204
  } else if (!password) {
4205
    tstrncpy(g_queryInfo.password, "taosdata", MAX_PASSWORD_SIZE);;
4206
  }
H
hzcheng 已提交
4207

4208
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
4209
  if (answerPrompt && answerPrompt->type == cJSON_String
4210
          && answerPrompt->valuestring != NULL) {
4211 4212 4213 4214
    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 已提交
4215
    } else {
4216
      g_args.answer_yes = false;
H
hzcheng 已提交
4217
    }
4218 4219 4220
  } else if (!answerPrompt) {
    g_args.answer_yes = false;
  } else {
4221
    printf("ERROR: failed to read json, confirm_parameter_prompt not found\n");
4222
    goto PARSE_OVER;
4223
  }
4224

4225 4226
  cJSON* gQueryTimes = cJSON_GetObjectItem(root, "query_times");
  if (gQueryTimes && gQueryTimes->type == cJSON_Number) {
4227
    if (gQueryTimes->valueint <= 0) {
4228 4229
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
        __func__, __LINE__);
4230 4231
      goto PARSE_OVER;
    }
4232 4233 4234 4235
    g_args.query_times = gQueryTimes->valueint;
  } else if (!gQueryTimes) {
    g_args.query_times = 1;
  } else {
4236
    errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4237
        __func__, __LINE__);
4238 4239 4240
    goto PARSE_OVER;
  }

4241 4242
  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (dbs && dbs->type == cJSON_String && dbs->valuestring != NULL) {
4243
    tstrncpy(g_queryInfo.dbName, dbs->valuestring, TSDB_DB_NAME_LEN);
4244
  } else if (!dbs) {
4245
    printf("ERROR: failed to read json, databases not found\n");
4246
    goto PARSE_OVER;
H
hzcheng 已提交
4247
  }
4248 4249 4250

  cJSON* queryMode = cJSON_GetObjectItem(root, "query_mode");
  if (queryMode && queryMode->type == cJSON_String && queryMode->valuestring != NULL) {
4251
    tstrncpy(g_queryInfo.queryMode, queryMode->valuestring, MAX_TB_NAME_SIZE);
4252
  } else if (!queryMode) {
4253
    tstrncpy(g_queryInfo.queryMode, "taosc", MAX_TB_NAME_SIZE);
4254
  } else {
4255
    printf("ERROR: failed to read json, query_mode not found\n");
4256
    goto PARSE_OVER;
H
hzcheng 已提交
4257
  }
4258

4259
  // specified_table_query
4260 4261
  cJSON *specifiedQuery = cJSON_GetObjectItem(root, "specified_table_query");
  if (!specifiedQuery) {
4262
    g_queryInfo.specifiedQueryInfo.concurrent = 1;
4263 4264
    g_queryInfo.specifiedQueryInfo.sqlCount = 0;
  } else if (specifiedQuery->type != cJSON_Object) {
4265
    printf("ERROR: failed to read json, super_table_query not found\n");
4266
    goto PARSE_OVER;
4267
  } else {
4268 4269 4270 4271 4272
    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;
4273 4274
    }

4275
    cJSON* specifiedQueryTimes = cJSON_GetObjectItem(specifiedQuery,
4276
        "query_times");
4277
    if (specifiedQueryTimes && specifiedQueryTimes->type == cJSON_Number) {
4278
      if (specifiedQueryTimes->valueint <= 0) {
4279 4280
        errorPrint(
                "%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
4281
          __func__, __LINE__, specifiedQueryTimes->valueint);
4282 4283 4284
        goto PARSE_OVER;

      }
4285 4286 4287 4288
      g_queryInfo.specifiedQueryInfo.queryTimes = specifiedQueryTimes->valueint;
    } else if (!specifiedQueryTimes) {
      g_queryInfo.specifiedQueryInfo.queryTimes = g_args.query_times;
    } else {
4289
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4290
          __func__, __LINE__);
4291
      goto PARSE_OVER;
4292
    }
4293

4294
    cJSON* concurrent = cJSON_GetObjectItem(specifiedQuery, "concurrent");
4295
    if (concurrent && concurrent->type == cJSON_Number) {
4296
      if (concurrent->valueint <= 0) {
4297
        errorPrint(
4298
                "%s() LN%d, query sqlCount %d or concurrent %d is not correct.\n",
4299 4300
              __func__, __LINE__,
              g_queryInfo.specifiedQueryInfo.sqlCount,
4301
              g_queryInfo.specifiedQueryInfo.concurrent);
4302 4303
        goto PARSE_OVER;
      }
4304
      g_queryInfo.specifiedQueryInfo.concurrent = concurrent->valueint;
4305
    } else if (!concurrent) {
4306
      g_queryInfo.specifiedQueryInfo.concurrent = 1;
4307
    }
4308

4309 4310 4311 4312 4313 4314 4315
    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;
4316
      } else {
4317
        errorPrint("%s() LN%d, failed to read json, async mode input error\n",
4318
            __func__, __LINE__);
4319 4320 4321
        goto PARSE_OVER;
      }
    } else {
4322
      g_queryInfo.specifiedQueryInfo.asyncMode = SYNC_MODE;
4323
    }
4324

4325
    cJSON* interval = cJSON_GetObjectItem(specifiedQuery, "interval");
4326
    if (interval && interval->type == cJSON_Number) {
4327
      g_queryInfo.specifiedQueryInfo.subscribeInterval = interval->valueint;
4328
    } else if (!interval) {
4329 4330
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4331
      g_queryInfo.specifiedQueryInfo.subscribeInterval = 10000;
4332
    }
4333

4334
    cJSON* restart = cJSON_GetObjectItem(specifiedQuery, "restart");
4335
    if (restart && restart->type == cJSON_String && restart->valuestring != NULL) {
4336
      if (0 == strcmp("yes", restart->valuestring)) {
4337
        g_queryInfo.specifiedQueryInfo.subscribeRestart = true;
4338
      } else if (0 == strcmp("no", restart->valuestring)) {
4339
        g_queryInfo.specifiedQueryInfo.subscribeRestart = false;
4340
      } else {
4341
        printf("ERROR: failed to read json, subscribe restart error\n");
4342 4343 4344
        goto PARSE_OVER;
      }
    } else {
4345
      g_queryInfo.specifiedQueryInfo.subscribeRestart = true;
4346
    }
4347

4348
    cJSON* keepProgress = cJSON_GetObjectItem(specifiedQuery, "keepProgress");
4349
    if (keepProgress
4350 4351
            && keepProgress->type == cJSON_String
            && keepProgress->valuestring != NULL) {
4352
      if (0 == strcmp("yes", keepProgress->valuestring)) {
4353
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 1;
4354
      } else if (0 == strcmp("no", keepProgress->valuestring)) {
4355
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4356
      } else {
4357
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
4358 4359 4360
        goto PARSE_OVER;
      }
    } else {
4361
      g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4362 4363
    }

4364
    // sqls
4365 4366
    cJSON* specifiedSqls = cJSON_GetObjectItem(specifiedQuery, "sqls");
    if (!specifiedSqls) {
4367
      g_queryInfo.specifiedQueryInfo.sqlCount = 0;
4368
    } else if (specifiedSqls->type != cJSON_Array) {
4369
      errorPrint("%s() LN%d, failed to read json, super sqls not found\n",
4370
          __func__, __LINE__);
4371
      goto PARSE_OVER;
4372
    } else {
4373 4374 4375 4376 4377 4378 4379 4380
      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);
4381 4382
        goto PARSE_OVER;
      }
4383

4384
      g_queryInfo.specifiedQueryInfo.sqlCount = superSqlSize;
4385
      for (int j = 0; j < superSqlSize; ++j) {
4386
        cJSON* sql = cJSON_GetArrayItem(specifiedSqls, j);
4387
        if (sql == NULL) continue;
4388

4389 4390
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
        if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) {
4391
          printf("ERROR: failed to read json, sql not found\n");
4392 4393
          goto PARSE_OVER;
        }
4394 4395
        tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j],
                sqlStr->valuestring, MAX_QUERY_SQL_LENGTH);
H
hzcheng 已提交
4396

4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407
        cJSON* endAfterConsume =
            cJSON_GetObjectItem(specifiedQuery, "endAfterConsume");
        if (endAfterConsume
                && endAfterConsume->type == cJSON_Number) {
            g_queryInfo.specifiedQueryInfo.endAfterConsume[j]
                = endAfterConsume->valueint;
        } else if (!endAfterConsume) {
            // default value is -1, which mean infinite loop
            g_queryInfo.specifiedQueryInfo.endAfterConsume[j] = -1;
        }

4408 4409
        cJSON* resubAfterConsume =
            cJSON_GetObjectItem(specifiedQuery, "resubAfterConsume");
4410 4411 4412
        if ((resubAfterConsume)
                && (resubAfterConsume->type == cJSON_Number)
                && (resubAfterConsume->valueint >= 0)) {
4413 4414 4415
            g_queryInfo.specifiedQueryInfo.resubAfterConsume[j]
                = resubAfterConsume->valueint;
        } else if (!resubAfterConsume) {
4416 4417
            // default value is -1, which mean do not resub
            g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] = -1;
4418 4419
        }

4420
        cJSON *result = cJSON_GetObjectItem(sql, "result");
4421 4422 4423 4424
        if ((NULL != result) && (result->type == cJSON_String)
                && (result->valuestring != NULL)) {
          tstrncpy(g_queryInfo.specifiedQueryInfo.result[j],
                  result->valuestring, MAX_FILE_NAME_LEN);
4425
        } else if (NULL == result) {
4426 4427
          memset(g_queryInfo.specifiedQueryInfo.result[j],
                  0, MAX_FILE_NAME_LEN);
4428
        } else {
4429
          printf("ERROR: failed to read json, super query result file not found\n");
4430
          goto PARSE_OVER;
4431
        }
4432 4433 4434
      }
    }
  }
4435

4436
  // super_table_query
4437 4438
  cJSON *superQuery = cJSON_GetObjectItem(root, "super_table_query");
  if (!superQuery) {
4439
    g_queryInfo.superQueryInfo.threadCnt = 1;
4440 4441
    g_queryInfo.superQueryInfo.sqlCount = 0;
  } else if (superQuery->type != cJSON_Object) {
4442
    printf("ERROR: failed to read json, sub_table_query not found\n");
4443 4444
    ret = true;
    goto PARSE_OVER;
H
hzcheng 已提交
4445
  } else {
4446
    cJSON* subrate = cJSON_GetObjectItem(superQuery, "query_interval");
4447
    if (subrate && subrate->type == cJSON_Number) {
4448
      g_queryInfo.superQueryInfo.queryInterval = subrate->valueint;
4449
    } else if (!subrate) {
4450
      g_queryInfo.superQueryInfo.queryInterval = 0;
4451 4452 4453 4454
    }

    cJSON* superQueryTimes = cJSON_GetObjectItem(superQuery, "query_times");
    if (superQueryTimes && superQueryTimes->type == cJSON_Number) {
4455 4456
      if (superQueryTimes->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
4457
          __func__, __LINE__, superQueryTimes->valueint);
4458 4459
        goto PARSE_OVER;
      }
4460 4461 4462 4463
      g_queryInfo.superQueryInfo.queryTimes = superQueryTimes->valueint;
    } else if (!superQueryTimes) {
      g_queryInfo.superQueryInfo.queryTimes = g_args.query_times;
    } else {
4464
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4465
          __func__, __LINE__);
4466
      goto PARSE_OVER;
4467
    }
4468

4469
    cJSON* threads = cJSON_GetObjectItem(superQuery, "threads");
4470
    if (threads && threads->type == cJSON_Number) {
4471 4472 4473 4474 4475 4476
      if (threads->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, threads input mistake\n",
          __func__, __LINE__);
        goto PARSE_OVER;

      }
4477
      g_queryInfo.superQueryInfo.threadCnt = threads->valueint;
4478
    } else if (!threads) {
4479
      g_queryInfo.superQueryInfo.threadCnt = 1;
4480
    }
4481

4482
    //cJSON* subTblCnt = cJSON_GetObjectItem(superQuery, "childtable_count");
4483
    //if (subTblCnt && subTblCnt->type == cJSON_Number) {
4484
    //  g_queryInfo.superQueryInfo.childTblCount = subTblCnt->valueint;
4485
    //} else if (!subTblCnt) {
4486
    //  g_queryInfo.superQueryInfo.childTblCount = 0;
4487
    //}
4488

4489
    cJSON* stblname = cJSON_GetObjectItem(superQuery, "stblname");
4490 4491 4492
    if (stblname && stblname->type == cJSON_String
        && stblname->valuestring != NULL) {
      tstrncpy(g_queryInfo.superQueryInfo.sTblName, stblname->valuestring,
4493
          TSDB_TABLE_NAME_LEN);
4494
    } else {
4495
      errorPrint("%s() LN%d, failed to read json, super table name input error\n",
4496
          __func__, __LINE__);
4497 4498
      goto PARSE_OVER;
    }
4499

4500 4501 4502 4503 4504 4505 4506
    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;
4507
      } else {
4508
        errorPrint("%s() LN%d, failed to read json, async mode input error\n",
4509
            __func__, __LINE__);
4510 4511 4512
        goto PARSE_OVER;
      }
    } else {
4513
      g_queryInfo.superQueryInfo.asyncMode = SYNC_MODE;
4514
    }
4515

4516 4517 4518 4519 4520 4521 4522 4523 4524
    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) {
4525 4526
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4527
      g_queryInfo.superQueryInfo.subscribeInterval = 10000;
4528
    }
4529

4530
    cJSON* subrestart = cJSON_GetObjectItem(superQuery, "restart");
4531 4532
    if (subrestart && subrestart->type == cJSON_String
        && subrestart->valuestring != NULL) {
4533
      if (0 == strcmp("yes", subrestart->valuestring)) {
4534
        g_queryInfo.superQueryInfo.subscribeRestart = true;
4535
      } else if (0 == strcmp("no", subrestart->valuestring)) {
4536
        g_queryInfo.superQueryInfo.subscribeRestart = false;
4537
      } else {
4538
        printf("ERROR: failed to read json, subscribe restart error\n");
4539 4540 4541
        goto PARSE_OVER;
      }
    } else {
4542
      g_queryInfo.superQueryInfo.subscribeRestart = true;
4543
    }
4544

4545 4546 4547 4548 4549
    cJSON* superkeepProgress = cJSON_GetObjectItem(superQuery, "keepProgress");
    if (superkeepProgress &&
            superkeepProgress->type == cJSON_String
            && superkeepProgress->valuestring != NULL) {
      if (0 == strcmp("yes", superkeepProgress->valuestring)) {
4550
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 1;
4551
      } else if (0 == strcmp("no", superkeepProgress->valuestring)) {
4552
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4553
      } else {
4554
        printf("ERROR: failed to read json, subscribe super table keepProgress error\n");
4555 4556 4557
        goto PARSE_OVER;
      }
    } else {
4558
      g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4559
    }
4560

4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571
    cJSON* superEndAfterConsume =
            cJSON_GetObjectItem(superQuery, "endAfterConsume");
    if (superEndAfterConsume
            && superEndAfterConsume->type == cJSON_Number) {
        g_queryInfo.superQueryInfo.endAfterConsume =
            superEndAfterConsume->valueint;
    } else if (!superEndAfterConsume) {
        // default value is -1, which mean do not resub
        g_queryInfo.superQueryInfo.endAfterConsume = -1;
    }

4572
    cJSON* superResubAfterConsume =
4573 4574 4575 4576 4577
            cJSON_GetObjectItem(superQuery, "resubAfterConsume");
    if ((superResubAfterConsume)
            && (superResubAfterConsume->type == cJSON_Number)
            && (superResubAfterConsume->valueint >= 0)) {
        g_queryInfo.superQueryInfo.resubAfterConsume =
4578 4579
            superResubAfterConsume->valueint;
    } else if (!superResubAfterConsume) {
4580
        // default value is -1, which mean do not resub
4581
        g_queryInfo.superQueryInfo.resubAfterConsume = -1;
4582 4583
    }

4584 4585 4586
    // supert table sqls
    cJSON* superSqls = cJSON_GetObjectItem(superQuery, "sqls");
    if (!superSqls) {
4587
      g_queryInfo.superQueryInfo.sqlCount = 0;
4588
    } else if (superSqls->type != cJSON_Array) {
4589
      errorPrint("%s() LN%d: failed to read json, super sqls not found\n",
4590
          __func__, __LINE__);
4591
      goto PARSE_OVER;
4592
    } else {
4593
      int superSqlSize = cJSON_GetArraySize(superSqls);
4594
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
4595
        errorPrint("%s() LN%d, failed to read json, query sql size overflow, max is %d\n",
4596
           __func__, __LINE__, MAX_QUERY_SQL_COUNT);
4597 4598
        goto PARSE_OVER;
      }
4599

4600
      g_queryInfo.superQueryInfo.sqlCount = superSqlSize;
4601
      for (int j = 0; j < superSqlSize; ++j) {
4602
        cJSON* sql = cJSON_GetArrayItem(superSqls, j);
4603
        if (sql == NULL) continue;
4604

4605
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
4606 4607 4608
        if (!sqlStr || sqlStr->type != cJSON_String
            || sqlStr->valuestring == NULL) {
          errorPrint("%s() LN%d, failed to read json, sql not found\n",
4609
              __func__, __LINE__);
4610 4611
          goto PARSE_OVER;
        }
4612
        tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring,
4613
            MAX_QUERY_SQL_LENGTH);
4614 4615

        cJSON *result = cJSON_GetObjectItem(sql, "result");
4616 4617 4618
        if (result != NULL && result->type == cJSON_String
            && result->valuestring != NULL){
          tstrncpy(g_queryInfo.superQueryInfo.result[j],
4619
              result->valuestring, MAX_FILE_NAME_LEN);
4620
        } else if (NULL == result) {
4621
          memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
4622
        }  else {
4623
          errorPrint("%s() LN%d, failed to read json, sub query result file not found\n",
4624
              __func__, __LINE__);
4625
          goto PARSE_OVER;
4626
        }
4627 4628
      }
    }
H
hzcheng 已提交
4629 4630
  }

4631
  ret = true;
H
hzcheng 已提交
4632

4633
PARSE_OVER:
4634 4635
  return ret;
}
H
hzcheng 已提交
4636

4637
static bool getInfoFromJsonFile(char* file) {
4638
    debugPrint("%s %d %s\n", __func__, __LINE__, file);
4639

4640 4641 4642 4643 4644
  FILE *fp = fopen(file, "r");
  if (!fp) {
    printf("failed to read %s, reason:%s\n", file, strerror(errno));
    return false;
  }
H
Hui Li 已提交
4645

4646
  bool  ret = false;
4647
  int   maxLen = 6400000;
4648 4649 4650 4651 4652 4653 4654
  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 已提交
4655
  }
H
Hui Li 已提交
4656

4657 4658 4659
  content[len] = 0;
  cJSON* root = cJSON_Parse(content);
  if (root == NULL) {
4660
    printf("ERROR: failed to cjson parse %s, invalid json format\n", file);
4661 4662
    goto PARSE_OVER;
  }
H
Hui Li 已提交
4663

4664 4665 4666
  cJSON* filetype = cJSON_GetObjectItem(root, "filetype");
  if (filetype && filetype->type == cJSON_String && filetype->valuestring != NULL) {
    if (0 == strcasecmp("insert", filetype->valuestring)) {
4667
      g_args.test_mode = INSERT_TEST;
4668
    } else if (0 == strcasecmp("query", filetype->valuestring)) {
4669
      g_args.test_mode = QUERY_TEST;
4670
    } else if (0 == strcasecmp("subscribe", filetype->valuestring)) {
4671
      g_args.test_mode = SUBSCRIBE_TEST;
4672
    } else {
4673
      printf("ERROR: failed to read json, filetype not support\n");
4674 4675 4676
      goto PARSE_OVER;
    }
  } else if (!filetype) {
4677
    g_args.test_mode = INSERT_TEST;
4678
  } else {
4679
    printf("ERROR: failed to read json, filetype not found\n");
4680 4681
    goto PARSE_OVER;
  }
H
hzcheng 已提交
4682

4683
  if (INSERT_TEST == g_args.test_mode) {
4684
    ret = getMetaFromInsertJsonFile(root);
4685
  } else if ((QUERY_TEST == g_args.test_mode)
4686
          || (SUBSCRIBE_TEST == g_args.test_mode)) {
4687 4688
    ret = getMetaFromQueryJsonFile(root);
  } else {
4689
    errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n",
4690
            __func__, __LINE__);
4691
    goto PARSE_OVER;
4692
  }
4693

4694
PARSE_OVER:
4695 4696
  free(content);
  cJSON_Delete(root);
H
hzcheng 已提交
4697
  fclose(fp);
4698 4699
  return ret;
}
H
hzcheng 已提交
4700

4701
static void prepareSampleData() {
4702
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4703 4704 4705
    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 已提交
4706
      }
4707 4708 4709 4710
    }
  }
}

4711
static void postFreeResource() {
4712
  tmfclose(g_fpOfInsertResult);
4713
  for (int i = 0; i < g_Dbs.dbCount; i++) {
S
Shuduo Sang 已提交
4714
    for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
4715 4716 4717
      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 已提交
4718
      }
4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730
      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 已提交
4731
    }
4732 4733
  }
}
S
Shuaiqiang Chang 已提交
4734

4735 4736 4737
static int getRowDataFromSample(
        char* dataBuf, int64_t maxLen, int64_t timestamp,
      SSuperTable* superTblInfo, int64_t* sampleUsePos) {
4738
  if ((*sampleUsePos) == MAX_SAMPLES_ONCE_FROM_FILE) {
4739
/*    int ret = readSampleFromCsvFileToMem(superTblInfo);
4740
    if (0 != ret) {
4741
      tmfree(superTblInfo->sampleDataBuf);
4742
      superTblInfo->sampleDataBuf = NULL;
4743 4744
      return -1;
    }
4745
*/
4746 4747
    *sampleUsePos = 0;
  }
S
Shuaiqiang Chang 已提交
4748

4749
  int    dataLen = 0;
4750

4751
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
4752
          "(%" PRId64 ", ", timestamp);
4753
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
4754
          "%s", superTblInfo->sampleDataBuf + superTblInfo->lenOfOneRow * (*sampleUsePos));
4755
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");
S
Shuaiqiang Chang 已提交
4756

4757
  (*sampleUsePos)++;
4758

4759 4760
  return dataLen;
}
S
Shuaiqiang Chang 已提交
4761

4762 4763
static int64_t generateStbRowData(
        SSuperTable* stbInfo,
4764 4765
        char* recBuf, int64_t timestamp)
{
4766
  int64_t   dataLen = 0;
4767
  char  *pstr = recBuf;
4768
  int64_t maxLen = MAX_DATA_SIZE;
4769

4770 4771
  dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
          "(%" PRId64 ",", timestamp);
4772

4773
  for (int i = 0; i < stbInfo->columnCount; i++) {
4774 4775 4776 4777
    if ((0 == strncasecmp(stbInfo->columns[i].dataType,
                    "BINARY", strlen("BINARY")))
            || (0 == strncasecmp(stbInfo->columns[i].dataType,
                    "NCHAR", strlen("NCHAR")))) {
4778
      if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) {
4779
        errorPrint( "binary or nchar length overflow, max size:%u\n",
4780
                (uint32_t)TSDB_MAX_BINARY_LEN);
4781
        return -1;
4782
      }
4783

4784 4785
      char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1);
      if (NULL == buf) {
4786
        errorPrint( "calloc failed! size:%d\n", stbInfo->columns[i].dataLen);
4787
        return -1;
4788 4789
      }
      rand_string(buf, stbInfo->columns[i].dataLen);
4790
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "\'%s\',", buf);
4791
      tmfree(buf);
4792
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4793
                "INT", strlen("INT"))) {
4794
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4795
              "%d,", rand_int());
4796
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4797
                "BIGINT", strlen("BIGINT"))) {
4798
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4799
              "%"PRId64",", rand_bigint());
4800
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4801
                "FLOAT", strlen("FLOAT"))) {
4802
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4803
              "%f,", rand_float());
4804
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4805
                "DOUBLE", strlen("DOUBLE"))) {
4806
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4807
              "%f,", rand_double());
4808
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4809
                "SMALLINT", strlen("SMALLINT"))) {
4810
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4811
          "%d,", rand_smallint());
4812
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4813
          "TINYINT", strlen("TINYINT"))) {
4814
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4815
          "%d,", rand_tinyint());
4816
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4817
          "BOOL", strlen("BOOL"))) {
4818
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4819
          "%d,", rand_bool());
4820
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4821
          "TIMESTAMP", strlen("TIMESTAMP"))) {
4822
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4823
          "%"PRId64",", rand_bigint());
4824
    }  else {
4825
      errorPrint( "No support data type: %s\n", stbInfo->columns[i].dataType);
4826
      return -1;
4827
    }
S
Shuaiqiang Chang 已提交
4828
  }
4829

4830
  dataLen -= 1;
4831
  dataLen += snprintf(pstr + dataLen, maxLen - dataLen, ")");
4832

4833 4834 4835
  verbosePrint("%s() LN%d, recBuf:\n\t%s\n", __func__, __LINE__, recBuf);

  return strlen(recBuf);
4836
}
S
Shuaiqiang Chang 已提交
4837

4838
static int64_t generateData(char *recBuf, char **data_type,
4839
        int64_t timestamp, int lenOfBinary) {
4840 4841
  memset(recBuf, 0, MAX_DATA_SIZE);
  char *pstr = recBuf;
4842 4843
  pstr += sprintf(pstr, "(%" PRId64, timestamp);

4844
  int columnCount = g_args.num_of_CPR;
4845

4846 4847
  for (int i = 0; i < columnCount; i++) {
    if (strcasecmp(data_type[i % columnCount], "TINYINT") == 0) {
4848
      pstr += sprintf(pstr, ",%d", rand_tinyint() );
4849
    } else if (strcasecmp(data_type[i % columnCount], "SMALLINT") == 0) {
4850
      pstr += sprintf(pstr, ",%d", rand_smallint());
4851
    } else if (strcasecmp(data_type[i % columnCount], "INT") == 0) {
4852
      pstr += sprintf(pstr, ",%d", rand_int());
4853
    } else if (strcasecmp(data_type[i % columnCount], "BIGINT") == 0) {
4854
      pstr += sprintf(pstr, ",%" PRId64, rand_bigint());
4855
    } else if (strcasecmp(data_type[i % columnCount], "TIMESTAMP") == 0) {
4856
      pstr += sprintf(pstr, ",%" PRId64, rand_bigint());
4857
    } else if (strcasecmp(data_type[i % columnCount], "FLOAT") == 0) {
4858
      pstr += sprintf(pstr, ",%10.4f", rand_float());
4859
    } else if (strcasecmp(data_type[i % columnCount], "DOUBLE") == 0) {
4860
      double t = rand_double();
4861
      pstr += sprintf(pstr, ",%20.8f", t);
4862
    } else if (strcasecmp(data_type[i % columnCount], "BOOL") == 0) {
4863
      bool b = rand_bool() & 1;
4864
      pstr += sprintf(pstr, ",%s", b ? "true" : "false");
4865
    } else if (strcasecmp(data_type[i % columnCount], "BINARY") == 0) {
4866 4867
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4868
      pstr += sprintf(pstr, ",\"%s\"", s);
4869
      free(s);
4870
    } else if (strcasecmp(data_type[i % columnCount], "NCHAR") == 0) {
4871 4872
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4873
      pstr += sprintf(pstr, ",\"%s\"", s);
4874 4875 4876
      free(s);
    }

4877
    if (strlen(recBuf) > MAX_DATA_SIZE) {
4878 4879 4880 4881 4882 4883 4884
      perror("column length too long, abort");
      exit(-1);
    }
  }

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

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

4887
  return (int32_t)strlen(recBuf);
4888 4889
}

4890
static int prepareSampleDataForSTable(SSuperTable *superTblInfo) {
4891 4892
  char* sampleDataBuf = NULL;

4893
  sampleDataBuf = calloc(
4894
            superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1);
4895
  if (sampleDataBuf == NULL) {
4896
      errorPrint("%s() LN%d, Failed to calloc %"PRIu64" Bytes, reason:%s\n",
4897 4898 4899 4900
              __func__, __LINE__,
              superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE,
              strerror(errno));
      return -1;
4901
  }
4902

4903 4904 4905 4906
  superTblInfo->sampleDataBuf = sampleDataBuf;
  int ret = readSampleFromCsvFileToMem(superTblInfo);

  if (0 != ret) {
4907 4908 4909 4910 4911
      errorPrint("%s() LN%d, read sample from csv file failed.\n",
          __func__, __LINE__);
      tmfree(sampleDataBuf);
      superTblInfo->sampleDataBuf = NULL;
      return -1;
H
Hui Li 已提交
4912
  }
4913

4914 4915 4916
  return 0;
}

4917
static int32_t execInsert(threadInfo *pThreadInfo, uint32_t k)
4918
{
4919 4920
    int32_t affectedRows;
    SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4921

4922
    verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
S
Shuduo Sang 已提交
4923
            __func__, __LINE__, pThreadInfo->buffer);
S
Shuduo Sang 已提交
4924

4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944
    uint16_t iface;
    if (superTblInfo)
        iface = superTblInfo->iface;
    else
        iface = g_args.iface;

    debugPrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
            __func__, __LINE__,
            (g_args.iface==TAOSC_IFACE)?
            "taosc":(g_args.iface==REST_IFACE)?"rest":"stmt");

    switch(iface) {
        case TAOSC_IFACE:
            affectedRows = queryDbExec(
                    pThreadInfo->taos,
                    pThreadInfo->buffer, INSERT_TYPE, false);
            break;

        case REST_IFACE:
            if (0 != postProceSql(g_Dbs.host, &g_Dbs.serv_addr, g_Dbs.port,
4945
                        pThreadInfo->buffer, pThreadInfo)) {
4946 4947 4948 4949 4950 4951 4952 4953
                affectedRows = -1;
                printf("========restful return fail, threadID[%d]\n",
                        pThreadInfo->threadID);
            } else {
                affectedRows = k;
            }
            break;

4954
#if STMT_IFACE_ENABLED == 1
4955 4956 4957 4958 4959 4960 4961 4962 4963
        case STMT_IFACE:
            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);
            }
            affectedRows = k;
            break;
4964
#endif
4965 4966 4967 4968 4969

        default:
            errorPrint("%s() LN%d: unknown insert mode: %d\n",
                    __func__, __LINE__, superTblInfo->iface);
            affectedRows = 0;
4970
    }
4971

4972
    return affectedRows;
4973 4974
}

4975 4976
static void getTableName(char *pTblName,
        threadInfo* pThreadInfo, uint64_t tableSeq)
4977
{
4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996
    SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
    if (superTblInfo) {
        if (AUTO_CREATE_SUBTBL != superTblInfo->autoCreateTable) {
            if (superTblInfo->childTblLimit > 0) {
                snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
                        superTblInfo->childTblName +
                        (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN);
            } else {
                verbosePrint("[%d] %s() LN%d: from=%"PRIu64" count=%"PRId64" seq=%"PRIu64"\n",
                        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);
            }
        } else {
            snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"",
                    superTblInfo->childTblPrefix, tableSeq);
        }
4997
    } else {
4998 4999
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"",
                g_args.tb_prefix, tableSeq);
5000 5001 5002
    }
}

5003
static int32_t generateDataTailWithoutStb(
5004
        uint32_t batch, char* buffer,
5005
        int64_t remainderBufLen, int64_t insertRows,
5006
        uint64_t recordFrom, int64_t startTime,
5007
        /* int64_t *pSamplePos, */int64_t *dataLen) {
5008

5009
  uint64_t len = 0;
5010 5011
  char *pstr = buffer;

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

5014
  int32_t k = 0;
5015
  for (k = 0; k < batch;) {
5016
    char data[MAX_DATA_SIZE];
5017 5018
    memset(data, 0, MAX_DATA_SIZE);

5019
    int64_t retLen = 0;
5020

5021 5022
    char **data_type = g_args.datatype;
    int lenOfBinary = g_args.len_of_binary;
5023

5024
    retLen = generateData(data, data_type,
5025
            startTime + getTSRandTail(
5026
                (int64_t) DEFAULT_TIMESTAMP_STEP, k,
5027 5028
                g_args.disorderRatio,
                g_args.disorderRange),
5029
            lenOfBinary);
5030

5031
    if (len > remainderBufLen)
5032
        break;
5033

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

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

5042
    recordFrom ++;
5043

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

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

5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069
static int64_t getTSRandTail(int64_t timeStampStep, int32_t seq,
        int disorderRatio, int disorderRange)
{
    int64_t randTail = timeStampStep * seq;
    if (disorderRatio > 0) {
        int rand_num = taosRandom() % 100;
        if(rand_num < disorderRatio) {
            randTail = (randTail +
                    (taosRandom() % disorderRange + 1)) * (-1);
            debugPrint("rand data generated, back %"PRId64"\n", randTail);
        }
    }

    return randTail;
}

static int32_t generateStbDataTail(
5070
        SSuperTable* superTblInfo,
5071
        uint32_t batch, char* buffer,
5072
        int64_t remainderBufLen, int64_t insertRows,
5073
        uint64_t recordFrom, int64_t startTime,
5074 5075 5076 5077 5078
        int64_t *pSamplePos, int64_t *dataLen) {
  uint64_t len = 0;

  char *pstr = buffer;

5079 5080 5081 5082 5083 5084
  bool tsRand;
  if (0 == strncasecmp(superTblInfo->dataSource, "rand", strlen("rand"))) {
      tsRand = true;
  } else {
      tsRand = false;
  }
5085
  verbosePrint("%s() LN%d batch=%u\n", __func__, __LINE__, batch);
5086

5087
  int32_t k = 0;
5088 5089 5090 5091 5092 5093
  for (k = 0; k < batch;) {
    char data[MAX_DATA_SIZE];
    memset(data, 0, MAX_DATA_SIZE);

    int64_t retLen = 0;

5094 5095 5096 5097 5098 5099 5100 5101 5102
    if (tsRand) {
        retLen = generateStbRowData(superTblInfo, data,
                startTime + getTSRandTail(
                    superTblInfo->timeStampStep, k,
                    superTblInfo->disorderRatio,
                    superTblInfo->disorderRange)
                );
    } else {
        retLen = getRowDataFromSample(
5103
                  data,
5104
                  remainderBufLen < MAX_DATA_SIZE ? remainderBufLen : MAX_DATA_SIZE,
5105 5106 5107 5108
                  startTime + superTblInfo->timeStampStep * k,
                  superTblInfo,
                  pSamplePos);
    }
5109

5110
    if (retLen > remainderBufLen) {
5111
        break;
5112 5113
    }

5114 5115 5116 5117 5118
    pstr += snprintf(pstr , retLen + 1, "%s", data);
    k++;
    len += retLen;
    remainderBufLen -= retLen;

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

5122
    recordFrom ++;
5123

5124
    if (recordFrom >= insertRows) {
5125
      break;
5126
    }
5127
  }
5128

5129 5130 5131
  *dataLen = len;
  return k;
}
5132

5133 5134 5135

static int generateSQLHeadWithoutStb(char *tableName,
        char *dbName,
5136
        char *buffer, int remainderBufLen)
5137 5138
{
  int len;
5139 5140 5141

  char headBuf[HEAD_BUFF_LEN];

5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167
  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) {
5168 5169
      char* tagsValBuf = NULL;
      if (0 == superTblInfo->tagSource) {
5170
            tagsValBuf = generateTagVaulesForStb(superTblInfo, tableSeq);
5171
      } else {
5172 5173 5174
            tagsValBuf = getTagValueFromTagSample(
                    superTblInfo,
                    tableSeq % superTblInfo->tagSampleCount);
5175 5176
      }
      if (NULL == tagsValBuf) {
5177
        errorPrint("%s() LN%d, tag buf failed to allocate  memory\n",
5178
            __func__, __LINE__);
5179 5180 5181
        return -1;
      }

5182 5183
      len = snprintf(
          headBuf,
5184 5185
                  HEAD_BUFF_LEN,
                  "%s.%s using %s.%s tags %s values",
5186
                  dbName,
5187
                  tableName,
5188
                  dbName,
5189 5190
                  superTblInfo->sTblName,
                  tagsValBuf);
5191 5192
      tmfree(tagsValBuf);
    } else if (TBL_ALREADY_EXISTS == superTblInfo->childTblExists) {
5193 5194
      len = snprintf(
          headBuf,
5195 5196
                  HEAD_BUFF_LEN,
                  "%s.%s values",
5197
                  dbName,
5198
                  tableName);
5199
    } else {
5200 5201
      len = snprintf(
          headBuf,
5202 5203
                  HEAD_BUFF_LEN,
                  "%s.%s values",
5204
                  dbName,
5205
                  tableName);
5206 5207
  }

5208 5209 5210 5211 5212
  if (len > remainderBufLen)
    return -1;

  tstrncpy(buffer, headBuf, len + 1);

5213 5214 5215
  return len;
}

5216
static int32_t generateStbInterlaceData(
5217
        SSuperTable *superTblInfo,
5218 5219 5220
        char *tableName, uint32_t batchPerTbl,
        uint64_t i,
        uint32_t batchPerTblTimes,
5221
        uint64_t tableSeq,
5222
        threadInfo *pThreadInfo, char *buffer,
5223
        int64_t insertRows,
5224
        int64_t startTime,
5225
        uint64_t *pRemainderBufLen)
5226
{
5227
  assert(buffer);
5228 5229
  char *pstr = buffer;

5230 5231 5232
  int headLen = generateStbSQLHead(
          superTblInfo,
          tableName, tableSeq, pThreadInfo->db_name,
5233
          pstr, *pRemainderBufLen);
5234 5235 5236 5237 5238

  if (headLen <= 0) {
    return 0;
  }
  // generate data buffer
5239
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" buffer:\n%s\n",
5240
            pThreadInfo->threadID, __func__, __LINE__, i, buffer);
5241 5242 5243 5244

  pstr += headLen;
  *pRemainderBufLen -= headLen;

5245
  int64_t dataLen = 0;
5246

5247
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" batchPerTblTimes=%u batchPerTbl = %u\n",
5248 5249
            pThreadInfo->threadID, __func__, __LINE__,
            i, batchPerTblTimes, batchPerTbl);
5250

5251
  if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
5252
      startTime = taosGetTimestamp(pThreadInfo->time_precision);
5253
  }
5254

5255
  int32_t k = generateStbDataTail(
5256 5257 5258 5259
            superTblInfo,
            batchPerTbl, pstr, *pRemainderBufLen, insertRows, 0,
            startTime,
            &(pThreadInfo->samplePos), &dataLen);
5260 5261 5262 5263

  if (k == batchPerTbl) {
    pstr += dataLen;
    *pRemainderBufLen -= dataLen;
5264
  } else {
5265
    debugPrint("%s() LN%d, generated data tail: %u, not equal batch per table: %u\n",
5266 5267 5268 5269 5270 5271 5272 5273 5274 5275
            __func__, __LINE__, k, batchPerTbl);
    pstr -= headLen;
    pstr[0] = '\0';
    k = 0;
  }

  return k;
}

static int64_t generateInterlaceDataWithoutStb(
5276
        char *tableName, uint32_t batch,
5277 5278 5279
        uint64_t tableSeq,
        char *dbName, char *buffer,
        int64_t insertRows,
5280
        int64_t startTime,
5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298
        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;

5299 5300
  int32_t k = generateDataTailWithoutStb(
            batch, pstr, *pRemainderBufLen, insertRows, 0,
5301
            startTime,
5302
            &dataLen);
5303

5304
  if (k == batch) {
5305 5306 5307
    pstr += dataLen;
    *pRemainderBufLen -= dataLen;
  } else {
5308 5309
    debugPrint("%s() LN%d, generated data tail: %d, not equal batch per table: %u\n",
            __func__, __LINE__, k, batch);
5310 5311
    pstr -= headLen;
    pstr[0] = '\0';
5312
    k = 0;
5313 5314 5315 5316 5317
  }

  return k;
}

5318
#if STMT_IFACE_ENABLED == 1
5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460
static int32_t prepareStmtBindArrayByType(TAOS_BIND *bind,
        char *dataType, int32_t dataLen, char **ptr)
{
    if (0 == strncasecmp(dataType,
                "BINARY", strlen("BINARY"))) {
        if (dataLen > TSDB_MAX_BINARY_LEN) {
            errorPrint( "binary length overflow, max size:%u\n",
                    (uint32_t)TSDB_MAX_BINARY_LEN);
            return -1;
        }
        char *bind_binary = (char *)*ptr;
        rand_string(bind_binary, dataLen);

        bind->buffer_type = TSDB_DATA_TYPE_BINARY;
        bind->buffer_length = dataLen;
        bind->buffer = bind_binary;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    } else if (0 == strncasecmp(dataType,
                "NCHAR", strlen("NCHAR"))) {
        if (dataLen > TSDB_MAX_BINARY_LEN) {
            errorPrint( "nchar length overflow, max size:%u\n",
                    (uint32_t)TSDB_MAX_BINARY_LEN);
            return -1;
        }
        char *bind_nchar = (char *)*ptr;
        rand_string(bind_nchar, dataLen);

        bind->buffer_type = TSDB_DATA_TYPE_NCHAR;
        bind->buffer_length = strlen(bind_nchar);
        bind->buffer = bind_nchar;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    } else if (0 == strncasecmp(dataType,
                "INT", strlen("INT"))) {
        int32_t *bind_int = (int32_t *)*ptr;

        *bind_int = rand_int();
        bind->buffer_type = TSDB_DATA_TYPE_INT;
        bind->buffer_length = sizeof(int32_t);
        bind->buffer = bind_int;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    } else if (0 == strncasecmp(dataType,
                "BIGINT", strlen("BIGINT"))) {
        int64_t *bind_bigint = (int64_t *)*ptr;

        *bind_bigint = rand_bigint();
        bind->buffer_type = TSDB_DATA_TYPE_BIGINT;
        bind->buffer_length = sizeof(int64_t);
        bind->buffer = bind_bigint;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "FLOAT", strlen("FLOAT"))) {
        float   *bind_float = (float *) *ptr;

        *bind_float = rand_float();
        bind->buffer_type = TSDB_DATA_TYPE_FLOAT;
        bind->buffer_length = sizeof(float);
        bind->buffer = bind_float;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "DOUBLE", strlen("DOUBLE"))) {
        double  *bind_double = (double *)*ptr;

        *bind_double = rand_double();
        bind->buffer_type = TSDB_DATA_TYPE_DOUBLE;
        bind->buffer_length = sizeof(double);
        bind->buffer = bind_double;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "SMALLINT", strlen("SMALLINT"))) {
        int16_t *bind_smallint = (int16_t *)*ptr;

        *bind_smallint = rand_smallint();
        bind->buffer_type = TSDB_DATA_TYPE_SMALLINT;
        bind->buffer_length = sizeof(int16_t);
        bind->buffer = bind_smallint;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "TINYINT", strlen("TINYINT"))) {
        int8_t  *bind_tinyint = (int8_t *)*ptr;

        *bind_tinyint = rand_tinyint();
        bind->buffer_type = TSDB_DATA_TYPE_TINYINT;
        bind->buffer_length = sizeof(int8_t);
        bind->buffer = bind_tinyint;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;
        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "BOOL", strlen("BOOL"))) {
        int8_t  *bind_bool = (int8_t *)*ptr;

        *bind_bool = rand_bool();
        bind->buffer_type = TSDB_DATA_TYPE_BOOL;
        bind->buffer_length = sizeof(int8_t);
        bind->buffer = bind_bool;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "TIMESTAMP", strlen("TIMESTAMP"))) {
        int64_t *bind_ts2 = (int64_t *) *ptr;

        *bind_ts2 = rand_bigint();
        bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
        bind->buffer_length = sizeof(int64_t);
        bind->buffer = bind_ts2;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else {
        errorPrint( "No support data type: %s\n",
                dataType);
        return -1;
    }

    return 0;
}

static int32_t prepareStmtWithoutStb(
5461
        TAOS_STMT *stmt,
5462 5463 5464 5465 5466
        char *tableName,
        uint32_t batch,
        int64_t insertRows,
        int64_t recordFrom,
        int64_t startTime)
5467
{
5468 5469 5470 5471 5472 5473 5474 5475
    int ret = taos_stmt_set_tbname(stmt, tableName);
    if (ret != 0) {
        errorPrint("failed to execute taos_stmt_set_tbname(%s). return 0x%x. reason: %s\n",
                tableName, ret, taos_errstr(NULL));
        return ret;
    }

    char **data_type = g_args.datatype;
5476

5477 5478 5479 5480 5481
    char *bindArray = malloc(sizeof(TAOS_BIND) * (g_args.num_of_CPR + 1));
    if (bindArray == NULL) {
        errorPrint("Failed to allocate %d bind params\n",
                (g_args.num_of_CPR + 1));
        return -1;
5482 5483
    }

5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528
    int32_t k = 0;
    for (k = 0; k < batch;) {
        /* columnCount + 1 (ts) */
        char data[MAX_DATA_SIZE];
        memset(data, 0, MAX_DATA_SIZE);

        char *ptr = data;
        TAOS_BIND *bind = (TAOS_BIND *)(bindArray + 0);

        int64_t *bind_ts;

        bind_ts = (int64_t *)ptr;
        bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
        *bind_ts = startTime + getTSRandTail(
                (int64_t)DEFAULT_TIMESTAMP_STEP, k,
                g_args.disorderRatio,
                g_args.disorderRange);
        bind->buffer_length = sizeof(int64_t);
        bind->buffer = bind_ts;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        ptr += bind->buffer_length;

        for (int i = 0; i < g_args.num_of_CPR; i ++) {
            bind = (TAOS_BIND *)((char *)bindArray + (sizeof(TAOS_BIND) * (i + 1)));
            if ( -1 == prepareStmtBindArrayByType(
                        bind,
                        data_type[i],
                        g_args.len_of_binary,
                        &ptr)) {
                return -1;
            }
        }
        taos_stmt_bind_param(stmt, (TAOS_BIND *)bindArray);
        // if msg > 3MB, break
        taos_stmt_add_batch(stmt);

        k++;
        recordFrom ++;
        if (recordFrom >= insertRows) {
            break;
        }
    }

5529
    free(bindArray);
5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543
    return k;
}

static int32_t prepareStbStmt(SSuperTable *stbInfo,
        TAOS_STMT *stmt,
        char *tableName, uint32_t batch,
        uint64_t insertRows,
        uint64_t recordFrom,
        int64_t startTime, char *buffer)
{
    int ret = taos_stmt_set_tbname(stmt, tableName);
    if (ret != 0) {
        errorPrint("failed to execute taos_stmt_set_tbname(%s). return 0x%x. reason: %s\n",
                tableName, ret, taos_errstr(NULL));
5544 5545 5546
        return ret;
    }

5547
    char *bindArray = malloc(sizeof(TAOS_BIND) * (stbInfo->columnCount + 1));
5548
    if (bindArray == NULL) {
5549 5550
        errorPrint("Failed to allocate %d bind params\n",
                (stbInfo->columnCount + 1));
5551 5552 5553 5554 5555 5556 5557 5558 5559
        return -1;
    }

    bool tsRand;
    if (0 == strncasecmp(stbInfo->dataSource, "rand", strlen("rand"))) {
        tsRand = true;
    } else {
        tsRand = false;
    }
5560 5561

    uint32_t k;
5562
    for (k = 0; k < batch;) {
5563
        /* columnCount + 1 (ts) */
5564 5565 5566 5567 5568
        char data[MAX_DATA_SIZE];
        memset(data, 0, MAX_DATA_SIZE);

        char *ptr = data;
        TAOS_BIND *bind = (TAOS_BIND *)(bindArray + 0);
5569

5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590
        int64_t *bind_ts;

        bind_ts = (int64_t *)ptr;
        bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
        if (tsRand) {
            *bind_ts = startTime + getTSRandTail(
                    stbInfo->timeStampStep, k,
                    stbInfo->disorderRatio,
                    stbInfo->disorderRange);
        } else {
            *bind_ts = startTime + stbInfo->timeStampStep * k;
        }
        bind->buffer_length = sizeof(int64_t);
        bind->buffer = bind_ts;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        ptr += bind->buffer_length;

        for (int i = 0; i < stbInfo->columnCount; i ++) {
            bind = (TAOS_BIND *)((char *)bindArray + (sizeof(TAOS_BIND) * (i + 1)));
5591 5592 5593 5594 5595 5596
            if ( -1 == prepareStmtBindArrayByType(
                        bind,
                        stbInfo->columns[i].dataType,
                        stbInfo->columns[i].dataLen,
                        &ptr)) {
                return -1;
5597 5598
            }
        }
5599
        taos_stmt_bind_param(stmt, (TAOS_BIND *)bindArray);
5600
        // if msg > 3MB, break
5601
        taos_stmt_add_batch(stmt);
5602

5603 5604 5605 5606 5607 5608
        k++;
        recordFrom ++;
        if (recordFrom >= insertRows) {
            break;
        }
    }
5609

5610
    free(bindArray);
5611 5612
    return k;
}
5613
#endif
5614 5615

static int32_t generateStbProgressiveData(
5616
        SSuperTable *superTblInfo,
5617
        char *tableName,
5618
        int64_t tableSeq,
5619
        char *dbName, char *buffer,
5620
        int64_t insertRows,
5621
        uint64_t recordFrom, int64_t startTime, int64_t *pSamplePos,
5622
        int64_t *pRemainderBufLen)
5623 5624
{
  assert(buffer != NULL);
5625
  char *pstr = buffer;
5626

5627
  memset(buffer, 0, *pRemainderBufLen);
5628

5629
  int64_t headLen = generateStbSQLHead(
5630
              superTblInfo,
5631
          tableName, tableSeq, dbName,
5632
          buffer, *pRemainderBufLen);
5633 5634 5635 5636

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

5640
  int64_t dataLen;
5641

5642
  return generateStbDataTail(superTblInfo,
5643
          g_args.num_of_RPR, pstr, *pRemainderBufLen,
5644
          insertRows, recordFrom,
5645 5646
          startTime,
          pSamplePos, &dataLen);
5647 5648
}

5649
static int32_t generateProgressiveDataWithoutStb(
5650
        char *tableName,
5651
        /* int64_t tableSeq, */
5652 5653
        threadInfo *pThreadInfo, char *buffer,
        int64_t insertRows,
5654
        uint64_t recordFrom, int64_t startTime, /*int64_t *pSamplePos, */
5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674
        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(
5675
          g_args.num_of_RPR, pstr, *pRemainderBufLen, insertRows, recordFrom,
5676 5677
          startTime,
          /*pSamplePos, */&dataLen);
5678
}
5679

5680 5681
static void printStatPerThread(threadInfo *pThreadInfo)
{
5682
    fprintf(stderr, "====thread[%d] completed total inserted rows: %"PRIu64 ", total affected rows: %"PRIu64". %.2f records/second====\n",
5683 5684 5685 5686 5687 5688
          pThreadInfo->threadID,
          pThreadInfo->totalInsertRows,
          pThreadInfo->totalAffectedRows,
          (double)(pThreadInfo->totalAffectedRows / (pThreadInfo->totalDelay/1000.0)));
}

5689
// sync write interlace data
5690
static void* syncWriteInterlace(threadInfo *pThreadInfo) {
5691
  debugPrint("[%d] %s() LN%d: ### interlace write\n",
5692 5693
         pThreadInfo->threadID, __func__, __LINE__);

5694
  int64_t insertRows;
5695
  uint32_t interlaceRows;
5696 5697 5698
  uint64_t maxSqlLen;
  int64_t nTimeStampStep;
  uint64_t insert_interval;
5699 5700

  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5701

5702 5703 5704 5705 5706 5707 5708 5709 5710
  if (superTblInfo) {
    insertRows = superTblInfo->insertRows;

    if ((superTblInfo->interlaceRows == 0)
        && (g_args.interlace_rows > 0)) {
      interlaceRows = g_args.interlace_rows;
    } else {
      interlaceRows = superTblInfo->interlaceRows;
    }
5711 5712 5713
    maxSqlLen = superTblInfo->maxSqlLen;
    nTimeStampStep = superTblInfo->timeStampStep;
    insert_interval = superTblInfo->insertInterval;
5714 5715 5716
  } else {
    insertRows = g_args.num_of_DPT;
    interlaceRows = g_args.interlace_rows;
5717 5718 5719
    maxSqlLen = g_args.max_sql_len;
    nTimeStampStep = DEFAULT_TIMESTAMP_STEP;
    insert_interval = g_args.insert_interval;
5720
  }
5721

5722 5723 5724 5725 5726
  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);

5727
  if (interlaceRows > insertRows)
H
Haojun Liao 已提交
5728
    interlaceRows = insertRows;
5729

5730 5731
  if (interlaceRows > g_args.num_of_RPR)
    interlaceRows = g_args.num_of_RPR;
5732

5733 5734
  uint32_t batchPerTbl = interlaceRows;
  uint32_t batchPerTblTimes;
5735

5736 5737 5738
  if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
    batchPerTblTimes =
        g_args.num_of_RPR / interlaceRows;
5739
  } else {
5740
    batchPerTblTimes = 1;
5741 5742
  }

S
Shuduo Sang 已提交
5743 5744
  pThreadInfo->buffer = calloc(maxSqlLen, 1);
  if (NULL == pThreadInfo->buffer) {
5745
    errorPrint( "%s() LN%d, Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5746
              __func__, __LINE__, maxSqlLen, strerror(errno));
5747 5748 5749 5750 5751 5752
    return NULL;
  }

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

5753 5754
  uint64_t st = 0;
  uint64_t et = UINT64_MAX;
5755

5756 5757 5758
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5759

5760
  uint64_t tableSeq = pThreadInfo->start_table_from;
5761 5762
  int64_t startTime = pThreadInfo->start_time;

5763
  uint64_t generatedRecPerTbl = 0;
5764
  bool flagSleep = true;
5765
  uint64_t sleepTimeTotal = 0;
5766

5767
  while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) {
5768
    if ((flagSleep) && (insert_interval)) {
5769 5770
        st = taosGetTimestampMs();
        flagSleep = false;
5771 5772
    }
    // generate data
S
Shuduo Sang 已提交
5773
    memset(pThreadInfo->buffer, 0, maxSqlLen);
5774
    uint64_t remainderBufLen = maxSqlLen;
5775

S
Shuduo Sang 已提交
5776
    char *pstr = pThreadInfo->buffer;
5777

5778 5779
    int len = snprintf(pstr,
            strlen(STR_INSERT_INTO) + 1, "%s", STR_INSERT_INTO);
5780 5781 5782
    pstr += len;
    remainderBufLen -= len;

5783
    uint32_t recOfBatch = 0;
5784

5785
    for (uint32_t i = 0; i < batchPerTblTimes; i ++) {
5786 5787
        char tableName[TSDB_TABLE_NAME_LEN];

5788
      getTableName(tableName, pThreadInfo, tableSeq);
5789 5790
      if (0 == strlen(tableName)) {
        errorPrint("[%d] %s() LN%d, getTableName return null\n",
5791
            pThreadInfo->threadID, __func__, __LINE__);
S
Shuduo Sang 已提交
5792
        free(pThreadInfo->buffer);
5793 5794
        return NULL;
      }
5795

5796
      uint64_t oldRemainderLen = remainderBufLen;
5797

5798
      int32_t generated;
5799
      if (superTblInfo) {
5800
          if (superTblInfo->iface == STMT_IFACE) {
5801
#if STMT_IFACE_ENABLED == 1
5802 5803 5804 5805 5806 5807 5808
              generated = prepareStbStmt(superTblInfo,
                      pThreadInfo->stmt,
                      tableName,
                      batchPerTbl,
                      insertRows, i,
                      startTime,
                      pThreadInfo->buffer);
5809 5810 5811
#else
              generated = -1;
#endif
5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822
          } else {
              generated = generateStbInterlaceData(
                      superTblInfo,
                      tableName, batchPerTbl, i,
                      batchPerTblTimes,
                      tableSeq,
                      pThreadInfo, pstr,
                      insertRows,
                      startTime,
                      &remainderBufLen);
          }
5823
      } else {
5824 5825 5826 5827 5828
          if (g_args.iface == STMT_IFACE) {
              debugPrint("[%d] %s() LN%d, tableName:%s, batch:%d startTime:%"PRId64"\n",
                      pThreadInfo->threadID,
                      __func__, __LINE__,
                      tableName, batchPerTbl, startTime);
5829
#if STMT_IFACE_ENABLED == 1
5830 5831 5832 5833 5834
              generated = prepareStmtWithoutStb(
                      pThreadInfo->stmt, tableName,
                      batchPerTbl,
                      insertRows, i,
                      startTime);
5835 5836 5837
#else
              generated = -1;
#endif
5838 5839 5840 5841 5842 5843 5844 5845 5846
          } else {
              generated = generateInterlaceDataWithoutStb(
                      tableName, batchPerTbl,
                      tableSeq,
                      pThreadInfo->db_name, pstr,
                      insertRows,
                      startTime,
                      &remainderBufLen);
          }
5847
      }
5848

5849
      debugPrint("[%d] %s() LN%d, generated records is %d\n",
5850
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5851
      if (generated < 0) {
5852
        errorPrint("[%d] %s() LN%d, generated records is %d\n",
5853
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5854
        goto free_of_interlace;
5855 5856
      } else if (generated == 0) {
        break;
5857 5858
      }

5859
      tableSeq ++;
5860
      recOfBatch += batchPerTbl;
5861

5862
      pstr += (oldRemainderLen - remainderBufLen);
5863
      pThreadInfo->totalInsertRows += batchPerTbl;
5864

5865
      verbosePrint("[%d] %s() LN%d batchPerTbl=%d recOfBatch=%d\n",
5866 5867
                pThreadInfo->threadID, __func__, __LINE__,
                batchPerTbl, recOfBatch);
5868

5869
      if (tableSeq == pThreadInfo->start_table_from + pThreadInfo->ntables) {
5870 5871 5872
            // turn to first table
            tableSeq = pThreadInfo->start_table_from;
            generatedRecPerTbl += batchPerTbl;
5873

5874 5875
            startTime = pThreadInfo->start_time
              + generatedRecPerTbl * nTimeStampStep;
5876

5877 5878 5879
            flagSleep = true;
            if (generatedRecPerTbl >= insertRows)
              break;
5880

5881
            int64_t remainRows = insertRows - generatedRecPerTbl;
5882 5883
            if ((remainRows > 0) && (batchPerTbl > remainRows))
              batchPerTbl = remainRows;
5884

5885 5886 5887
            if (pThreadInfo->ntables * batchPerTbl < g_args.num_of_RPR)
                break;
      }
5888

5889
      verbosePrint("[%d] %s() LN%d generatedRecPerTbl=%"PRId64" insertRows=%"PRId64"\n",
5890 5891
                pThreadInfo->threadID, __func__, __LINE__,
                generatedRecPerTbl, insertRows);
5892 5893

      if ((g_args.num_of_RPR - recOfBatch) < batchPerTbl)
5894 5895 5896
        break;
    }

5897
    verbosePrint("[%d] %s() LN%d recOfBatch=%d totalInsertRows=%"PRIu64"\n",
5898 5899
              pThreadInfo->threadID, __func__, __LINE__, recOfBatch,
              pThreadInfo->totalInsertRows);
5900
    verbosePrint("[%d] %s() LN%d, buffer=%s\n",
S
Shuduo Sang 已提交
5901
           pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->buffer);
5902

5903
    startTs = taosGetTimestampMs();
5904

5905
    if (recOfBatch == 0) {
5906
      errorPrint("[%d] %s() LN%d try inserting records of batch is %d\n",
5907 5908 5909 5910 5911
              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 已提交
5912
    int64_t affectedRows = execInsert(pThreadInfo, recOfBatch);
5913

5914
    endTs = taosGetTimestampMs();
5915 5916
    uint64_t delay = endTs - startTs;
    performancePrint("%s() LN%d, insert execution time is %"PRIu64"ms\n",
5917
            __func__, __LINE__, delay);
5918 5919 5920
    verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5921 5922 5923 5924 5925 5926

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

5927
    if (recOfBatch != affectedRows) {
5928
        errorPrint("[%d] %s() LN%d execInsert insert %d, affected rows: %"PRId64"\n%s\n",
5929
                pThreadInfo->threadID, __func__, __LINE__,
S
Shuduo Sang 已提交
5930
                recOfBatch, affectedRows, pThreadInfo->buffer);
5931
        goto free_of_interlace;
5932
    }
5933

5934
    pThreadInfo->totalAffectedRows += affectedRows;
5935

5936 5937
    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
5938
      printf("thread[%d] has currently inserted rows: %"PRIu64 ", affected rows: %"PRIu64 "\n",
5939 5940 5941
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5942 5943
      lastPrintTime = currentPrintTime;
    }
5944

5945
    if ((insert_interval) && flagSleep) {
5946
      et = taosGetTimestampMs();
5947

5948
      if (insert_interval > (et - st) ) {
S
Shuduo Sang 已提交
5949 5950
        uint64_t sleepTime = insert_interval - (et -st);
        performancePrint("%s() LN%d sleep: %"PRId64" ms for insert interval\n",
5951
                    __func__, __LINE__, sleepTime);
5952 5953 5954
        taosMsleep(sleepTime); // ms
        sleepTimeTotal += insert_interval;
      }
5955
    }
5956 5957
  }

5958
free_of_interlace:
S
Shuduo Sang 已提交
5959
  tmfree(pThreadInfo->buffer);
5960
  printStatPerThread(pThreadInfo);
5961 5962 5963
  return NULL;
}

5964
// sync insertion progressive data
5965
static void* syncWriteProgressive(threadInfo *pThreadInfo) {
5966
  debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__);
5967

5968
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5969
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5970 5971 5972 5973 5974 5975
  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);
5976

S
Shuduo Sang 已提交
5977 5978
  pThreadInfo->buffer = calloc(maxSqlLen, 1);
  if (NULL == pThreadInfo->buffer) {
5979
    errorPrint( "Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5980 5981
              maxSqlLen,
              strerror(errno));
5982 5983
    return NULL;
  }
5984

5985 5986 5987
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5988

5989 5990
  pThreadInfo->totalInsertRows = 0;
  pThreadInfo->totalAffectedRows = 0;
5991

5992
  pThreadInfo->samplePos = 0;
5993

5994 5995 5996
  for (uint64_t tableSeq = pThreadInfo->start_table_from;
          tableSeq <= pThreadInfo->end_table_to;
          tableSeq ++) {
5997
    int64_t start_time = pThreadInfo->start_time;
5998

5999
    for (uint64_t i = 0; i < insertRows;) {
6000 6001
      char tableName[TSDB_TABLE_NAME_LEN];
      getTableName(tableName, pThreadInfo, tableSeq);
6002
      verbosePrint("%s() LN%d: tid=%d seq=%"PRId64" tableName=%s\n",
6003 6004
             __func__, __LINE__,
             pThreadInfo->threadID, tableSeq, tableName);
6005 6006 6007 6008 6009 6010
      if (0 == strlen(tableName)) {
        errorPrint("[%d] %s() LN%d, getTableName return null\n",
            pThreadInfo->threadID, __func__, __LINE__);
        free(pThreadInfo->buffer);
        return NULL;
      }
6011

6012
      int64_t remainderBufLen = maxSqlLen;
S
Shuduo Sang 已提交
6013
      char *pstr = pThreadInfo->buffer;
6014

6015 6016
      int len = snprintf(pstr,
              strlen(STR_INSERT_INTO) + 1, "%s", STR_INSERT_INTO);
6017 6018 6019 6020

      pstr += len;
      remainderBufLen -= len;

6021
      int32_t generated;
6022
      if (superTblInfo) {
6023
          if (superTblInfo->iface == STMT_IFACE) {
6024
#if STMT_IFACE_ENABLED == 1
6025 6026
              generated = prepareStbStmt(
                      superTblInfo,
6027
                      pThreadInfo->stmt,
6028 6029
                      tableName,
                      g_args.num_of_RPR,
6030
                      insertRows, i, start_time, pstr);
6031 6032 6033
#else
              generated = -1;
#endif
6034 6035 6036 6037 6038 6039 6040 6041
          } else {
              generated = generateStbProgressiveData(
                      superTblInfo,
                      tableName, tableSeq, pThreadInfo->db_name, pstr,
                      insertRows, i, start_time,
                      &(pThreadInfo->samplePos),
                      &remainderBufLen);
          }
6042
      } else {
6043
          if (g_args.iface == STMT_IFACE) {
6044
#if STMT_IFACE_ENABLED == 1
6045 6046 6047 6048 6049 6050
              generated = prepareStmtWithoutStb(
                      pThreadInfo->stmt,
                      tableName,
                      g_args.num_of_RPR,
                      insertRows, i,
                      start_time);
6051 6052 6053
#else
              generated = -1;
#endif
6054 6055 6056 6057 6058 6059 6060 6061 6062
          } else {
              generated = generateProgressiveDataWithoutStb(
                      tableName,
                      /*  tableSeq, */
                      pThreadInfo, pstr, insertRows,
                      i, start_time,
                      /* &(pThreadInfo->samplePos), */
                      &remainderBufLen);
          }
6063
      }
6064 6065 6066
      if (generated > 0)
        i += generated;
      else
6067
        goto free_of_progressive;
6068

6069
      start_time +=  generated * timeStampStep;
6070
      pThreadInfo->totalInsertRows += generated;
6071

6072
      startTs = taosGetTimestampMs();
6073

6074
      int32_t affectedRows = execInsert(pThreadInfo, generated);
6075

6076
      endTs = taosGetTimestampMs();
6077
      uint64_t delay = endTs - startTs;
6078
      performancePrint("%s() LN%d, insert execution time is %"PRId64"ms\n",
6079
              __func__, __LINE__, delay);
6080
      verbosePrint("[%d] %s() LN%d affectedRows=%d\n",
6081 6082
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
6083

6084 6085 6086 6087
      if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
      if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
      pThreadInfo->cntDelay++;
      pThreadInfo->totalDelay += delay;
6088

6089
      if (affectedRows < 0) {
6090
        errorPrint("%s() LN%d, affected rows: %d\n",
6091 6092 6093
                __func__, __LINE__, affectedRows);
        goto free_of_progressive;
      }
6094 6095 6096

      pThreadInfo->totalAffectedRows += affectedRows;

6097 6098
      int64_t  currentPrintTime = taosGetTimestampMs();
      if (currentPrintTime - lastPrintTime > 30*1000) {
6099
        printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
6100 6101 6102
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
6103 6104 6105
        lastPrintTime = currentPrintTime;
      }

6106
      if (i >= insertRows)
6107 6108 6109
        break;
    }   // num_of_DPT

6110 6111
    if ((g_args.verbose_print) &&
      (tableSeq == pThreadInfo->ntables - 1) && (superTblInfo) &&
6112 6113
        (0 == strncasecmp(
                    superTblInfo->dataSource, "sample", strlen("sample")))) {
6114
          verbosePrint("%s() LN%d samplePos=%"PRId64"\n",
6115
                  __func__, __LINE__, pThreadInfo->samplePos);
6116
    }
6117
  } // tableSeq
6118

6119
free_of_progressive:
S
Shuduo Sang 已提交
6120
  tmfree(pThreadInfo->buffer);
6121
  printStatPerThread(pThreadInfo);
6122
  return NULL;
H
Hui Li 已提交
6123 6124
}

6125 6126
static void* syncWrite(void *sarg) {

6127 6128
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
6129

6130
  uint32_t interlaceRows;
6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141

  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;
  }
6142

6143
  if (interlaceRows > 0) {
6144
    // interlace mode
6145
    return syncWriteInterlace(pThreadInfo);
6146 6147
  } else {
    // progressive mode
6148
    return syncWriteProgressive(pThreadInfo);
6149 6150 6151
  }
}

6152
static void callBack(void *param, TAOS_RES *res, int code) {
6153 6154
  threadInfo* pThreadInfo = (threadInfo*)param;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
6155

6156 6157
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
6158
  if (insert_interval) {
6159 6160 6161
    pThreadInfo->et = taosGetTimestampMs();
    if ((pThreadInfo->et - pThreadInfo->st) < insert_interval) {
      taosMsleep(insert_interval - (pThreadInfo->et - pThreadInfo->st)); // ms
6162
    }
H
Hui Li 已提交
6163
  }
6164

6165
  char *buffer = calloc(1, pThreadInfo->superTblInfo->maxSqlLen);
6166
  char data[MAX_DATA_SIZE];
6167
  char *pstr = buffer;
6168 6169
  pstr += sprintf(pstr, "insert into %s.%s%"PRId64" values",
          pThreadInfo->db_name, pThreadInfo->tb_prefix,
6170
          pThreadInfo->start_table_from);
6171 6172 6173 6174 6175 6176 6177
//  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);
6178 6179 6180 6181
    free(buffer);
    taos_free_result(res);
    return;
  }
6182

6183
  for (int i = 0; i < g_args.num_of_RPR; i++) {
6184
    int rand_num = taosRandom() % 100;
6185
    if (0 != pThreadInfo->superTblInfo->disorderRatio
6186
            && rand_num < pThreadInfo->superTblInfo->disorderRatio) {
6187 6188 6189
      int64_t d = pThreadInfo->lastTs
          - (taosRandom() % pThreadInfo->superTblInfo->disorderRange + 1);
      generateStbRowData(pThreadInfo->superTblInfo, data, d);
6190
    } else {
6191 6192
      generateStbRowData(pThreadInfo->superTblInfo,
              data, pThreadInfo->lastTs += 1000);
H
Hui Li 已提交
6193
    }
6194
    pstr += sprintf(pstr, "%s", data);
6195
    pThreadInfo->counter++;
H
Hui Li 已提交
6196

6197
    if (pThreadInfo->counter >= pThreadInfo->superTblInfo->insertRows) {
6198
      break;
H
Hui Li 已提交
6199 6200
    }
  }
6201

6202
  if (insert_interval) {
6203
    pThreadInfo->st = taosGetTimestampMs();
6204
  }
6205
  taos_query_a(pThreadInfo->taos, buffer, callBack, pThreadInfo);
6206
  free(buffer);
H
Hui Li 已提交
6207

6208
  taos_free_result(res);
H
Hui Li 已提交
6209 6210
}

6211
static void *asyncWrite(void *sarg) {
6212 6213
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
6214

6215 6216 6217
  pThreadInfo->st = 0;
  pThreadInfo->et = 0;
  pThreadInfo->lastTs = pThreadInfo->start_time;
6218

6219
  int insert_interval =
6220
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
6221
  if (insert_interval) {
6222
    pThreadInfo->st = taosGetTimestampMs();
H
Hui Li 已提交
6223
  }
6224
  taos_query_a(pThreadInfo->taos, "show databases", callBack, pThreadInfo);
6225

6226
  tsem_wait(&(pThreadInfo->lock_sem));
H
Hui Li 已提交
6227 6228 6229 6230

  return NULL;
}

6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256
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;
}

6257
static void startMultiThreadInsertData(int threads, char* db_name,
6258
        char* precision,SSuperTable* superTblInfo) {
6259

6260 6261 6262 6263
  int32_t timePrec = TSDB_TIME_PRECISION_MILLI;
  if (0 != precision[0]) {
    if (0 == strncasecmp(precision, "ms", 2)) {
      timePrec = TSDB_TIME_PRECISION_MILLI;
6264
    } else if (0 == strncasecmp(precision, "us", 2)) {
6265
      timePrec = TSDB_TIME_PRECISION_MICRO;
6266 6267 6268
    } else if (0 == strncasecmp(precision, "ns", 2)) {
      timePrec = TSDB_TIME_PRECISION_NANO;
    } else {
6269
      errorPrint("Not support precision: %s\n", precision);
6270 6271 6272 6273
      exit(-1);
    }
  }

6274
  int64_t start_time;
6275 6276
  if (superTblInfo) {
    if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
6277
        start_time = taosGetTimestamp(timePrec);
6278
    } else {
6279
      if (TSDB_CODE_SUCCESS != taosParseTime(
6280 6281 6282 6283 6284
        superTblInfo->startTimestamp,
        &start_time,
        strlen(superTblInfo->startTimestamp),
        timePrec, 0)) {
          ERROR_EXIT("failed to parse time!\n");
6285
      }
6286
    }
6287
  } else {
6288
     start_time = 1500000000000;
6289 6290
  }

6291
  int64_t start = taosGetTimestampMs();
6292

6293
  // read sample data from file first
6294
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
6295
              "sample", strlen("sample")))) {
6296
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
6297
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
6298
              __func__, __LINE__);
6299 6300 6301 6302
      exit(-1);
    }
  }

6303
  TAOS* taos0 = taos_connect(
6304 6305
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
6306
  if (NULL == taos0) {
6307
    errorPrint("%s() LN%d, connect to server fail , reason: %s\n",
6308
                __func__, __LINE__, taos_errstr(NULL));
6309 6310 6311
    exit(-1);
  }

S
Shuduo Sang 已提交
6312
  int64_t ntables = 0;
6313
  uint64_t tableFrom;
6314

6315
  if (superTblInfo) {
6316 6317
    int64_t limit;
    uint64_t offset;
6318

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

6324
    if (superTblInfo->childTblExists == TBL_ALREADY_EXISTS) {
6325 6326
      if ((superTblInfo->childTblLimit < 0)
          || ((superTblInfo->childTblOffset + superTblInfo->childTblLimit)
6327
            > (superTblInfo->childTblCount))) {
6328 6329 6330 6331 6332 6333
        superTblInfo->childTblLimit =
            superTblInfo->childTblCount - superTblInfo->childTblOffset;
      }

      offset = superTblInfo->childTblOffset;
      limit = superTblInfo->childTblLimit;
6334
    } else {
6335 6336
      limit = superTblInfo->childTblCount;
      offset = 0;
6337 6338
    }

6339
    ntables = limit;
6340
    tableFrom = offset;
6341

6342 6343 6344 6345
    if ((superTblInfo->childTblExists != TBL_NO_EXISTS)
        && ((superTblInfo->childTblOffset + superTblInfo->childTblLimit )
            > superTblInfo->childTblCount)) {
      printf("WARNING: specified offset + limit > child table count!\n");
6346
      prompt();
6347 6348 6349
    }

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

6355
    superTblInfo->childTblName = (char*)calloc(1,
6356
        limit * TSDB_TABLE_NAME_LEN);
6357
    if (superTblInfo->childTblName == NULL) {
6358
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
6359
      taos_close(taos0);
6360 6361 6362
      exit(-1);
    }

6363
    int64_t childTblCount;
6364
    getChildNameOfSuperTableWithLimitAndOffset(
6365
        taos0,
6366 6367 6368 6369
        db_name, superTblInfo->sTblName,
        &superTblInfo->childTblName, &childTblCount,
        limit,
        offset);
6370 6371
  } else {
    ntables = g_args.num_of_tables;
6372
    tableFrom = 0;
6373
  }
6374

6375
  taos_close(taos0);
6376

S
Shuduo Sang 已提交
6377
  int64_t a = ntables / threads;
6378 6379 6380 6381 6382
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

S
Shuduo Sang 已提交
6383
  int64_t b = 0;
6384 6385 6386 6387
  if (threads != 0) {
    b = ntables % threads;
  }

6388
  if ((superTblInfo)
6389 6390 6391
      && (superTblInfo->iface == REST_IFACE)) {
      if (convertHostToServAddr(
                  g_Dbs.host, g_Dbs.port, &(g_Dbs.serv_addr)) != 0) {
6392 6393
        exit(-1);
      }
6394 6395
  }

6396 6397 6398 6399 6400 6401 6402 6403 6404
  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 已提交
6405
  for (int i = 0; i < threads; i++) {
6406 6407
    threadInfo *pThreadInfo = infos + i;
    pThreadInfo->threadID = i;
6408
    tstrncpy(pThreadInfo->db_name, db_name, TSDB_DB_NAME_LEN);
6409 6410
    pThreadInfo->time_precision = timePrec;
    pThreadInfo->superTblInfo = superTblInfo;
6411

6412 6413
    pThreadInfo->start_time = start_time;
    pThreadInfo->minDelay = UINT64_MAX;
6414

6415
    if ((NULL == superTblInfo) ||
6416 6417
            (superTblInfo->iface != REST_IFACE)) {
      //t_info->taos = taos;
6418
      pThreadInfo->taos = taos_connect(
6419 6420
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
6421
      if (NULL == pThreadInfo->taos) {
6422
        errorPrint(
6423 6424
                "%s() LN%d, connect to server fail from insert sub thread, reason: %s\n",
                __func__, __LINE__,
6425
                taos_errstr(NULL));
6426
        free(infos);
6427 6428
        exit(-1);
      }
6429

6430
#if STMT_IFACE_ENABLED == 1
6431 6432 6433 6434 6435 6436 6437 6438 6439 6440
      if ((g_args.iface == STMT_IFACE)
          || ((superTblInfo) && (superTblInfo->iface == STMT_IFACE))) {

          int columnCount;
          if (superTblInfo) {
              columnCount = superTblInfo->columnCount;
          } else {
              columnCount = g_args.num_of_CPR;
          }

6441 6442
        pThreadInfo->stmt = taos_stmt_init(pThreadInfo->taos);
        if (NULL == pThreadInfo->stmt) {
6443 6444 6445 6446 6447 6448 6449 6450
            errorPrint(
                "%s() LN%d, failed init stmt, reason: %s\n",
                __func__, __LINE__,
                taos_errstr(NULL));
            free(pids);
            free(infos);
            exit(-1);
        }
6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468

        char buffer[3000];
        char *pstr = buffer;
        pstr += sprintf(pstr, "INSERT INTO ? values(?");

        for (int col = 0; col < columnCount; col ++) {
            pstr += sprintf(pstr, ",?");
        }
        pstr += sprintf(pstr, ")");

        int ret = taos_stmt_prepare(pThreadInfo->stmt, buffer, 0);
        if (ret != 0){
            errorPrint("failed to execute taos_stmt_prepare. return 0x%x. reason: %s\n",
                    ret, taos_errstr(NULL));
            free(pids);
            free(infos);
            exit(-1);
        }
6469
      }
6470
#endif
6471
    } else {
6472
      pThreadInfo->taos = NULL;
6473 6474
    }

6475
/*    if ((NULL == superTblInfo)
6476
            || (0 == superTblInfo->multiThreadWriteOneTbl)) {
6477
            */
6478
      pThreadInfo->start_table_from = tableFrom;
6479
      pThreadInfo->ntables = i<b?a+1:a;
6480 6481
      pThreadInfo->end_table_to = i < b ? tableFrom + a : tableFrom + a - 1;
      tableFrom = pThreadInfo->end_table_to + 1;
6482
/*    } else {
6483 6484 6485
      pThreadInfo->start_table_from = 0;
      pThreadInfo->ntables = superTblInfo->childTblCount;
      pThreadInfo->start_time = pThreadInfo->start_time + rand_int() % 10000 - rand_tinyint();
6486
    }
6487
*/
6488
    tsem_init(&(pThreadInfo->lock_sem), 0, 0);
6489
    if (ASYNC_MODE == g_Dbs.asyncMode) {
6490
      pthread_create(pids + i, NULL, asyncWrite, pThreadInfo);
6491
    } else {
6492
      pthread_create(pids + i, NULL, syncWrite, pThreadInfo);
6493
    }
H
Hui Li 已提交
6494
  }
6495

H
Hui Li 已提交
6496 6497 6498 6499
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

6500 6501 6502 6503
  uint64_t totalDelay = 0;
  uint64_t maxDelay = 0;
  uint64_t minDelay = UINT64_MAX;
  uint64_t cntDelay = 1;
6504 6505
  double  avgDelay = 0;

H
Hui Li 已提交
6506
  for (int i = 0; i < threads; i++) {
6507
    threadInfo *pThreadInfo = infos + i;
6508

6509
    tsem_destroy(&(pThreadInfo->lock_sem));
6510

6511
#if STMT_IFACE_ENABLED == 1
6512 6513
    if (pThreadInfo->stmt) {
      taos_stmt_close(pThreadInfo->stmt);
6514
    }
6515
#endif
6516 6517
    tsem_destroy(&(pThreadInfo->lock_sem));
    taos_close(pThreadInfo->taos);
6518

6519
    debugPrint("%s() LN%d, [%d] totalInsert=%"PRIu64" totalAffected=%"PRIu64"\n",
6520
            __func__, __LINE__,
6521 6522
            pThreadInfo->threadID, pThreadInfo->totalInsertRows,
            pThreadInfo->totalAffectedRows);
6523
    if (superTblInfo) {
6524 6525
        superTblInfo->totalAffectedRows += pThreadInfo->totalAffectedRows;
        superTblInfo->totalInsertRows += pThreadInfo->totalInsertRows;
6526
    } else {
6527 6528
        g_args.totalAffectedRows += pThreadInfo->totalAffectedRows;
        g_args.totalInsertRows += pThreadInfo->totalInsertRows;
6529
    }
6530

6531 6532 6533 6534
    totalDelay  += pThreadInfo->totalDelay;
    cntDelay   += pThreadInfo->cntDelay;
    if (pThreadInfo->maxDelay > maxDelay) maxDelay = pThreadInfo->maxDelay;
    if (pThreadInfo->minDelay < minDelay) minDelay = pThreadInfo->minDelay;
H
Hui Li 已提交
6535
  }
6536
  cntDelay -= 1;
H
Hui Li 已提交
6537

6538
  if (cntDelay == 0)    cntDelay = 1;
6539 6540
  avgDelay = (double)totalDelay / cntDelay;

6541 6542
  int64_t end = taosGetTimestampMs();
  int64_t t = end - start;
6543 6544

  if (superTblInfo) {
6545
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
6546 6547 6548 6549
          t / 1000.0, superTblInfo->totalInsertRows,
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
6550 6551 6552 6553

    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",
6554 6555 6556 6557
          t / 1000.0, superTblInfo->totalInsertRows,
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
6558
    }
6559
  } else {
6560
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n",
6561 6562 6563 6564
          t / 1000.0, g_args.totalInsertRows,
          g_args.totalAffectedRows,
          threads, db_name,
          (double)g_args.totalInsertRows / (t / 1000.0));
6565 6566 6567
    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",
6568 6569 6570 6571
          t * 1000.0, g_args.totalInsertRows,
          g_args.totalAffectedRows,
          threads, db_name,
          (double)g_args.totalInsertRows / (t / 1000.0));
6572
    }
6573
  }
6574

6575
  fprintf(stderr, "insert delay, avg: %10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
6576
          avgDelay, maxDelay, minDelay);
6577 6578
  if (g_fpOfInsertResult) {
    fprintf(g_fpOfInsertResult, "insert delay, avg:%10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
6579
          avgDelay, maxDelay, minDelay);
6580
  }
6581

6582 6583
  //taos_close(taos);

H
Hui Li 已提交
6584
  free(pids);
6585
  free(infos);
H
Hui Li 已提交
6586 6587
}

6588
static void *readTable(void *sarg) {
6589
#if 1
6590 6591
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  TAOS *taos = pThreadInfo->taos;
H
hzcheng 已提交
6592
  char command[BUFFER_SIZE] = "\0";
6593 6594 6595
  uint64_t sTime = pThreadInfo->start_time;
  char *tb_prefix = pThreadInfo->tb_prefix;
  FILE *fp = fopen(pThreadInfo->filePath, "a");
H
Hui Li 已提交
6596
  if (NULL == fp) {
6597
    errorPrint( "fopen %s fail, reason:%s.\n", pThreadInfo->filePath, strerror(errno));
H
Hui Li 已提交
6598 6599
    return NULL;
  }
6600

6601
  int64_t num_of_DPT;
6602 6603
/*  if (pThreadInfo->superTblInfo) {
    num_of_DPT = pThreadInfo->superTblInfo->insertRows; //  nrecords_per_table;
6604
  } else {
6605
  */
6606
      num_of_DPT = g_args.num_of_DPT;
6607
//  }
6608

6609
  int64_t num_of_tables = pThreadInfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
S
Shuduo Sang 已提交
6610
  int64_t totalData = num_of_DPT * num_of_tables;
6611
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
6612 6613 6614 6615 6616

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

6620
  for (int j = 0; j < n; j++) {
H
hzcheng 已提交
6621
    double totalT = 0;
6622
    uint64_t count = 0;
6623 6624
    for (int64_t i = 0; i < num_of_tables; i++) {
      sprintf(command, "select %s from %s%"PRId64" where ts>= %" PRIu64,
6625
              aggreFunc[j], tb_prefix, i, sTime);
H
hzcheng 已提交
6626

6627
      double t = taosGetTimestampMs();
S
Shuaiqiang Chang 已提交
6628 6629
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);
H
hzcheng 已提交
6630

S
Shuaiqiang Chang 已提交
6631
      if (code != 0) {
6632
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
6633
        taos_free_result(pSql);
H
hzcheng 已提交
6634
        taos_close(taos);
6635
        fclose(fp);
6636
        return NULL;
H
hzcheng 已提交
6637 6638
      }

6639
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
6640 6641 6642
        count++;
      }

6643
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
6644 6645
      totalT += t;

S
Shuaiqiang Chang 已提交
6646
      taos_free_result(pSql);
H
hzcheng 已提交
6647 6648
    }

6649
    fprintf(fp, "|%10s  |   %"PRId64"   |  %12.2f   |   %10.2f  |\n",
S
slguan 已提交
6650
            aggreFunc[j][0] == '*' ? "   *   " : aggreFunc[j], totalData,
H
hzcheng 已提交
6651
            (double)(num_of_tables * num_of_DPT) / totalT, totalT * 1000);
6652
    printf("select %10s took %.6f second(s)\n", aggreFunc[j], totalT * 1000);
H
hzcheng 已提交
6653 6654 6655
  }
  fprintf(fp, "\n");
  fclose(fp);
6656
#endif
H
hzcheng 已提交
6657 6658 6659
  return NULL;
}

6660
static void *readMetric(void *sarg) {
6661
#if 1
6662 6663
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  TAOS *taos = pThreadInfo->taos;
H
hzcheng 已提交
6664
  char command[BUFFER_SIZE] = "\0";
6665
  FILE *fp = fopen(pThreadInfo->filePath, "a");
H
Hui Li 已提交
6666
  if (NULL == fp) {
6667
    printf("fopen %s fail, reason:%s.\n", pThreadInfo->filePath, strerror(errno));
H
Hui Li 已提交
6668 6669
    return NULL;
  }
6670

6671 6672
  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 已提交
6673
  int64_t totalData = num_of_DPT * num_of_tables;
6674
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
6675 6676 6677 6678 6679

  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 已提交
6680 6681
  printf("%"PRId64" records:\n", totalData);
  fprintf(fp, "Querying On %"PRId64" records:\n", totalData);
H
hzcheng 已提交
6682 6683

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

6687
    int64_t m = 10 < num_of_tables ? 10 : num_of_tables;
H
hzcheng 已提交
6688

6689
    for (int64_t i = 1; i <= m; i++) {
H
hzcheng 已提交
6690
      if (i == 1) {
6691
        sprintf(tempS, "t1 = %"PRId64"", i);
H
hzcheng 已提交
6692
      } else {
6693
        sprintf(tempS, " or t1 = %"PRId64" ", i);
H
hzcheng 已提交
6694
      }
6695
      strncat(condition, tempS, COND_BUF_LEN - 1);
H
hzcheng 已提交
6696

L
liu0x54 已提交
6697
      sprintf(command, "select %s from meters where %s", aggreFunc[j], condition);
H
hzcheng 已提交
6698 6699 6700 6701

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

6702
      double t = taosGetTimestampMs();
H
hzcheng 已提交
6703

S
Shuaiqiang Chang 已提交
6704 6705 6706 6707
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);

      if (code != 0) {
6708
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
6709
        taos_free_result(pSql);
H
hzcheng 已提交
6710
        taos_close(taos);
6711
        fclose(fp);
6712
        return NULL;
H
hzcheng 已提交
6713 6714
      }
      int count = 0;
6715
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
6716 6717
        count++;
      }
6718
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
6719

6720
      fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n",
6721 6722
              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 已提交
6723

S
Shuaiqiang Chang 已提交
6724
      taos_free_result(pSql);
H
hzcheng 已提交
6725 6726 6727 6728
    }
    fprintf(fp, "\n");
  }
  fclose(fp);
6729
#endif
H
hzcheng 已提交
6730 6731 6732
  return NULL;
}

6733 6734 6735 6736 6737 6738 6739
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 已提交
6740

6741
static int insertTestProcess() {
6742

6743 6744 6745
  setupForAnsiEscape();
  int ret = printfInsertMeta();
  resetAfterAnsiEscape();
6746

6747 6748 6749
  if (ret == -1)
    exit(EXIT_FAILURE);

6750
  debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile);
6751 6752
  g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a");
  if (NULL == g_fpOfInsertResult) {
6753
    errorPrint( "Failed to open %s for save result\n", g_Dbs.resultFile);
6754 6755
    return -1;
  }
6756

6757 6758
  if (g_fpOfInsertResult)
    printfInsertMetaToFile(g_fpOfInsertResult);
6759

6760
  prompt();
6761

6762 6763 6764
  init_rand_data();

  // create database and super tables
6765
  if(createDatabasesAndStables() != 0) {
6766 6767
    if (g_fpOfInsertResult)
      fclose(g_fpOfInsertResult);
6768 6769
    return -1;
  }
6770 6771

  // pretreatement
6772
  prepareSampleData();
6773

6774 6775 6776 6777
  double start;
  double end;

  // create child tables
6778
  start = taosGetTimestampMs();
6779
  createChildTables();
6780
  end = taosGetTimestampMs();
6781

6782
  if (g_totalChildTables > 0) {
6783
    fprintf(stderr, "Spent %.4f seconds to create %"PRId64" tables with %d thread(s)\n\n",
6784
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6785 6786
    if (g_fpOfInsertResult) {
      fprintf(g_fpOfInsertResult,
6787
            "Spent %.4f seconds to create %"PRId64" tables with %d thread(s)\n\n",
6788
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6789
    }
6790
  }
6791

6792
  // create sub threads for inserting data
6793
  //start = taosGetTimestampMs();
6794
  for (int i = 0; i < g_Dbs.dbCount; i++) {
6795 6796
    if (g_Dbs.use_metric) {
      if (g_Dbs.db[i].superTblCount > 0) {
S
Shuduo Sang 已提交
6797
        for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
6798 6799 6800 6801 6802

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

          if (superTblInfo && (superTblInfo->insertRows > 0)) {
            startMultiThreadInsertData(
6803 6804 6805 6806
              g_Dbs.threadCount,
              g_Dbs.db[i].dbName,
              g_Dbs.db[i].dbCfg.precision,
              superTblInfo);
6807
          }
6808
        }
6809
      }
6810
    } else {
6811
        startMultiThreadInsertData(
6812 6813 6814
          g_Dbs.threadCount,
          g_Dbs.db[i].dbName,
          g_Dbs.db[i].dbCfg.precision,
6815
          NULL);
H
Hui Li 已提交
6816
    }
6817
  }
6818
  //end = taosGetTimestampMs();
6819

6820
  //int64_t    totalInsertRows = 0;
6821
  //int64_t    totalAffectedRows = 0;
6822
  //for (int i = 0; i < g_Dbs.dbCount; i++) {
6823
  //  for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
6824
  //  totalInsertRows+= g_Dbs.db[i].superTbls[j].totalInsertRows;
6825 6826
  //  totalAffectedRows += g_Dbs.db[i].superTbls[j].totalAffectedRows;
  //}
6827
  //printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s)\n\n", end - start, totalInsertRows, totalAffectedRows, g_Dbs.threadCount);
6828
  postFreeResource();
6829

6830 6831 6832
  return 0;
}

6833 6834
static void *specifiedTableQuery(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6835

6836
  if (pThreadInfo->taos == NULL) {
6837 6838
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
6839 6840 6841 6842
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
          g_queryInfo.port);
6843 6844
    if (taos == NULL) {
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6845
            pThreadInfo->threadID, taos_errstr(NULL));
6846 6847
      return NULL;
    } else {
6848
      pThreadInfo->taos = taos;
6849 6850 6851
    }
  }

6852
  char sqlStr[TSDB_DB_NAME_LEN + 5];
6853
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6854 6855
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6856 6857 6858 6859
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
    return NULL;
  }
6860

6861 6862
  uint64_t st = 0;
  uint64_t et = 0;
6863

6864
  uint64_t queryTimes = g_queryInfo.specifiedQueryInfo.queryTimes;
6865

6866 6867 6868
  uint64_t totalQueried = 0;
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
6869

6870
  if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != '\0') {
6871
    sprintf(pThreadInfo->filePath, "%s-%d",
6872 6873 6874 6875
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
  }

6876
  while(queryTimes --) {
6877
    if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) <
6878
            (int64_t)g_queryInfo.specifiedQueryInfo.queryInterval) {
6879
      taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval - (et - st)); // ms
6880 6881
    }

6882 6883 6884
    st = taosGetTimestampMs();

    selectAndGetResult(pThreadInfo,
6885
          g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq]);
6886

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

6891 6892
    totalQueried ++;
    g_queryInfo.specifiedQueryInfo.totalQueried ++;
6893

6894 6895
    uint64_t  currentPrintTime = taosGetTimestampMs();
    uint64_t  endTs = taosGetTimestampMs();
6896
    if (currentPrintTime - lastPrintTime > 30*1000) {
6897
      debugPrint("%s() LN%d, endTs=%"PRIu64"ms, startTs=%"PRIu64"ms\n",
6898
          __func__, __LINE__, endTs, startTs);
6899
      printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.6f\n",
6900 6901
                    pThreadInfo->threadID,
                    totalQueried,
6902
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6903
      lastPrintTime = currentPrintTime;
6904
    }
H
Hui Li 已提交
6905
  }
6906 6907
  return NULL;
}
H
Hui Li 已提交
6908

6909
static void replaceChildTblName(char* inSql, char* outSql, int tblIndex) {
6910 6911
  char sourceString[32] = "xxxx";
  char subTblName[MAX_TB_NAME_SIZE*3];
6912 6913
  sprintf(subTblName, "%s.%s",
          g_queryInfo.dbName,
6914
          g_queryInfo.superQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN);
6915 6916

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

6918 6919
  char* pos = strstr(inSql, sourceString);
  if (0 == pos) {
6920
    return;
H
Hui Li 已提交
6921
  }
6922

6923
  tstrncpy(outSql, inSql, pos - inSql + 1);
6924
  //printf("1: %s\n", outSql);
6925
  strncat(outSql, subTblName, MAX_QUERY_SQL_LENGTH - 1);
6926
  //printf("2: %s\n", outSql);
6927
  strncat(outSql, pos+strlen(sourceString), MAX_QUERY_SQL_LENGTH - 1);
6928
  //printf("3: %s\n", outSql);
H
Hui Li 已提交
6929 6930
}

6931
static void *superTableQuery(void *sarg) {
6932
  char sqlstr[MAX_QUERY_SQL_LENGTH];
6933
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6934

6935
  if (pThreadInfo->taos == NULL) {
6936 6937 6938 6939 6940 6941 6942 6943
    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",
6944
            pThreadInfo->threadID, taos_errstr(NULL));
6945 6946
      return NULL;
    } else {
6947
      pThreadInfo->taos = taos;
6948 6949 6950
    }
  }

6951 6952
  uint64_t st = 0;
  uint64_t et = (int64_t)g_queryInfo.superQueryInfo.queryInterval;
6953

6954 6955 6956
  uint64_t queryTimes = g_queryInfo.superQueryInfo.queryTimes;
  uint64_t totalQueried = 0;
  uint64_t  startTs = taosGetTimestampMs();
6957

6958
  uint64_t  lastPrintTime = taosGetTimestampMs();
6959
  while(queryTimes --) {
6960 6961 6962
    if (g_queryInfo.superQueryInfo.queryInterval
            && (et - st) < (int64_t)g_queryInfo.superQueryInfo.queryInterval) {
      taosMsleep(g_queryInfo.superQueryInfo.queryInterval - (et - st)); // ms
6963
      //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6964
    }
H
Hui Li 已提交
6965

6966
    st = taosGetTimestampMs();
6967
    for (int i = pThreadInfo->start_table_from; i <= pThreadInfo->end_table_to; i++) {
6968
      for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
6969
        memset(sqlstr,0,sizeof(sqlstr));
6970
        replaceChildTblName(g_queryInfo.superQueryInfo.sql[j], sqlstr, i);
6971
        if (g_queryInfo.superQueryInfo.result[j][0] != '\0') {
6972
          sprintf(pThreadInfo->filePath, "%s-%d",
6973
                  g_queryInfo.superQueryInfo.result[j],
6974
                  pThreadInfo->threadID);
6975
        }
6976
        selectAndGetResult(pThreadInfo, sqlstr);
6977 6978 6979 6980 6981 6982 6983

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

        int64_t  currentPrintTime = taosGetTimestampMs();
        int64_t  endTs = taosGetTimestampMs();
        if (currentPrintTime - lastPrintTime > 30*1000) {
6984
          printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.3f\n",
6985 6986
                    pThreadInfo->threadID,
                    totalQueried,
6987
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6988
          lastPrintTime = currentPrintTime;
6989
        }
6990
      }
H
Hui Li 已提交
6991
    }
6992
    et = taosGetTimestampMs();
6993
    printf("####thread[%"PRId64"] complete all sqls to allocate all sub-tables[%"PRIu64" - %"PRIu64"] once queries duration:%.4fs\n\n",
6994
            taosGetSelfPthreadId(),
6995 6996
            pThreadInfo->start_table_from,
            pThreadInfo->end_table_to,
6997
            (double)(et - st)/1000.0);
6998
  }
6999

7000 7001 7002
  return NULL;
}

7003
static int queryTestProcess() {
7004 7005 7006 7007

  setupForAnsiEscape();
  printfQueryMeta();
  resetAfterAnsiEscape();
7008 7009 7010 7011 7012 7013

  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
7014
          g_queryInfo.port);
7015
  if (taos == NULL) {
7016 7017
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
7018 7019 7020
    exit(-1);
  }

7021
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
7022 7023
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
7024 7025 7026
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
7027
  }
7028

7029
  prompt();
7030

7031 7032 7033
  if (g_args.debug_print || g_args.verbose_print) {
    printfQuerySystemInfo(taos);
  }
7034

7035 7036 7037 7038 7039 7040
  if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
    if (convertHostToServAddr(
        g_queryInfo.host, g_queryInfo.port, &g_queryInfo.serv_addr) != 0)
      exit(-1);
  }

7041 7042 7043
  pthread_t  *pids  = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from specify table
7044
  int nConcurrent = g_queryInfo.specifiedQueryInfo.concurrent;
7045
  uint64_t nSqlCount = g_queryInfo.specifiedQueryInfo.sqlCount;
7046

7047
  uint64_t startTs = taosGetTimestampMs();
7048

7049 7050 7051 7052 7053 7054
  if ((nSqlCount > 0) && (nConcurrent > 0)) {

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

    if ((NULL == pids) || (NULL == infos)) {
7055
      taos_close(taos);
7056
      ERROR_EXIT("memory allocation failed for create threads\n");
7057
    }
7058

7059 7060 7061
    for (uint64_t i = 0; i < nSqlCount; i++) {
        for (int j = 0; j < nConcurrent; j++) {
            uint64_t seq = i * nConcurrent + j;
7062 7063 7064
            threadInfo *pThreadInfo = infos + seq;
            pThreadInfo->threadID = seq;
            pThreadInfo->querySeq = i;
7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078

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

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

7080
            pThreadInfo->taos = NULL;// TODO: workaround to use separate taos connection;
7081

7082
            pthread_create(pids + seq, NULL, specifiedTableQuery,
7083
                pThreadInfo);
7084
        }
7085
    }
7086
  } else {
7087
    g_queryInfo.specifiedQueryInfo.concurrent = 0;
7088
  }
7089

7090 7091
  taos_close(taos);

7092 7093 7094
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
  //==== create sub threads for query from all sub table of the super table
7095 7096 7097 7098
  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));
7099 7100

    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
7101 7102
      free(infos);
      free(pids);
7103

7104
      ERROR_EXIT("memory allocation failed for create threads\n");
7105
    }
7106

S
Shuduo Sang 已提交
7107
    int64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
7108
    int threads = g_queryInfo.superQueryInfo.threadCnt;
7109

S
Shuduo Sang 已提交
7110
    int64_t a = ntables / threads;
7111 7112 7113 7114
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
7115

S
Shuduo Sang 已提交
7116
    int64_t b = 0;
7117 7118 7119
    if (threads != 0) {
      b = ntables % threads;
    }
7120

7121
    uint64_t tableFrom = 0;
7122
    for (int i = 0; i < threads; i++) {
7123 7124
      threadInfo *pThreadInfo = infosOfSub + i;
      pThreadInfo->threadID = i;
7125

7126
      pThreadInfo->start_table_from = tableFrom;
7127
      pThreadInfo->ntables = i<b?a+1:a;
7128 7129
      pThreadInfo->end_table_to = i < b ? tableFrom + a : tableFrom + a - 1;
      tableFrom = pThreadInfo->end_table_to + 1;
7130 7131
      pThreadInfo->taos = NULL; // TODO: workaround to use separate taos connection;
      pthread_create(pidsOfSub + i, NULL, superTableQuery, pThreadInfo);
7132 7133
    }

7134
    g_queryInfo.superQueryInfo.threadCnt = threads;
7135
  } else {
7136
    g_queryInfo.superQueryInfo.threadCnt = 0;
7137
  }
7138

7139 7140 7141 7142 7143 7144
  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);
      }
    }
7145
  }
S
Shuaiqiang Chang 已提交
7146

7147
  tmfree((char*)pids);
7148
  tmfree((char*)infos);
7149

7150
  for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
7151
    pthread_join(pidsOfSub[i], NULL);
H
hzcheng 已提交
7152
  }
H
Hui Li 已提交
7153

7154
  tmfree((char*)pidsOfSub);
7155
  tmfree((char*)infosOfSub);
7156

7157
//  taos_close(taos);// TODO: workaround to use separate taos connection;
7158
  uint64_t endTs = taosGetTimestampMs();
7159

7160
  uint64_t totalQueried = g_queryInfo.specifiedQueryInfo.totalQueried +
7161 7162
    g_queryInfo.superQueryInfo.totalQueried;

7163
  fprintf(stderr, "==== completed total queries: %"PRIu64", the QPS of all threads: %10.3f====\n",
7164
          totalQueried,
7165
          (double)(totalQueried/((endTs-startTs)/1000.0)));
7166 7167 7168
  return 0;
}

7169 7170 7171 7172 7173 7174 7175 7176 7177
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)
7178
    fetchResult(res, (threadInfo *)param);
7179 7180 7181 7182 7183
  // tao_unscribe() will free result.
}

static void specified_sub_callback(
        TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
7184
  if (res == NULL || taos_errno(res) != 0) {
7185 7186
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
7187 7188
    return;
  }
7189

7190
  if (param)
7191
    fetchResult(res, (threadInfo *)param);
7192
  // tao_unscribe() will free result.
H
hzcheng 已提交
7193 7194
}

7195
static TAOS_SUB* subscribeImpl(
7196 7197 7198 7199
        QUERY_CLASS class,
        threadInfo *pThreadInfo,
        char *sql, char* topic, bool restart, uint64_t interval)
{
7200
  TAOS_SUB* tsub = NULL;
H
hzcheng 已提交
7201

7202 7203 7204 7205
  if ((SPECIFIED_CLASS == class)
          && (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode)) {
    tsub = taos_subscribe(
            pThreadInfo->taos,
7206
            restart,
7207
            topic, sql, specified_sub_callback, (void*)pThreadInfo,
7208
            g_queryInfo.specifiedQueryInfo.subscribeInterval);
7209 7210 7211 7212 7213 7214 7215
  } 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);
7216
  } else {
7217 7218
    tsub = taos_subscribe(
            pThreadInfo->taos,
7219
            restart,
7220
            topic, sql, NULL, NULL, interval);
7221
  }
7222

7223 7224 7225
  if (tsub == NULL) {
    printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
    return NULL;
7226
  }
7227

7228 7229
  return tsub;
}
H
hzcheng 已提交
7230

7231 7232
static void *superSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
7233
  char subSqlstr[MAX_QUERY_SQL_LENGTH];
7234
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
7235
  uint64_t tsubSeq;
H
hzcheng 已提交
7236

7237 7238
  if (pThreadInfo->ntables > MAX_QUERY_SQL_COUNT) {
      errorPrint("The table number(%"PRId64") of the thread is more than max query sql count: %d\n",
7239 7240 7241 7242 7243
              pThreadInfo->ntables,
              MAX_QUERY_SQL_COUNT);
      exit(-1);
  }

7244
  if (pThreadInfo->taos == NULL) {
7245
    pThreadInfo->taos = taos_connect(g_queryInfo.host,
7246 7247 7248 7249
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
          g_queryInfo.port);
7250
    if (pThreadInfo->taos == NULL) {
7251
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
7252
            pThreadInfo->threadID, taos_errstr(NULL));
7253 7254 7255 7256
      return NULL;
    }
  }

7257 7258
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
7259 7260
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
7261 7262
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
7263 7264
    return NULL;
  }
7265

S
Shengliang Guan 已提交
7266 7267 7268
  char topic[32] = {0};
  for (uint64_t i = pThreadInfo->start_table_from;
          i <= pThreadInfo->end_table_to; i++) {
7269 7270

      tsubSeq = i - pThreadInfo->start_table_from;
7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282
      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) {
7283
        sprintf(pThreadInfo->filePath, "%s-%d",
7284 7285 7286 7287 7288 7289
                g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
      }

      debugPrint("%s() LN%d, [%d] subSqlstr: %s\n",
              __func__, __LINE__, pThreadInfo->threadID, subSqlstr);
7290
      tsub[tsubSeq] = subscribeImpl(
7291 7292 7293 7294
              STABLE_CLASS,
              pThreadInfo, subSqlstr, topic,
              g_queryInfo.superQueryInfo.subscribeRestart,
              g_queryInfo.superQueryInfo.subscribeInterval);
7295
      if (NULL == tsub[tsubSeq]) {
7296
        taos_close(pThreadInfo->taos);
7297 7298
        return NULL;
      }
S
Shengliang Guan 已提交
7299
  }
7300 7301

  // start loop to consume result
7302 7303 7304 7305
  int consumed[MAX_QUERY_SQL_COUNT];
  for (int i = 0; i < MAX_QUERY_SQL_COUNT; i++) {
    consumed[i] = 0;
  }
7306
  TAOS_RES* res = NULL;
7307

7308 7309
  uint64_t st = 0, et = 0;

7310 7311 7312 7313
  while ((g_queryInfo.superQueryInfo.endAfterConsume == -1)
          || (g_queryInfo.superQueryInfo.endAfterConsume <
              consumed[pThreadInfo->end_table_to - pThreadInfo->start_table_from])) {

7314 7315
    for (uint64_t i = pThreadInfo->start_table_from;
            i <= pThreadInfo->end_table_to; i++) {
7316 7317 7318 7319
      tsubSeq = i - pThreadInfo->start_table_from;
      if (ASYNC_MODE == g_queryInfo.superQueryInfo.asyncMode) {
          continue;
      }
7320

7321 7322
      st = taosGetTimestampMs();
      performancePrint("st: %"PRIu64" et: %"PRIu64" st-et: %"PRIu64"\n", st, et, (st - et));
7323
      res = taos_consume(tsub[tsubSeq]);
7324 7325 7326
      et = taosGetTimestampMs();
      performancePrint("st: %"PRIu64" et: %"PRIu64" delta: %"PRIu64"\n", st, et, (et - st));

7327 7328
      if (res) {
          if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
7329
              sprintf(pThreadInfo->filePath, "%s-%d",
7330 7331
                      g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
                      pThreadInfo->threadID);
7332
              fetchResult(res, pThreadInfo);
7333 7334 7335
          }
          consumed[tsubSeq] ++;

7336
          if ((g_queryInfo.superQueryInfo.resubAfterConsume != -1)
7337
                  && (consumed[tsubSeq] >=
7338
                      g_queryInfo.superQueryInfo.resubAfterConsume)) {
7339 7340 7341 7342
              printf("keepProgress:%d, resub super table query: %"PRIu64"\n",
                      g_queryInfo.superQueryInfo.subscribeKeepProgress,
                      pThreadInfo->querySeq);
              taos_unsubscribe(tsub[tsubSeq],
7343
                    g_queryInfo.superQueryInfo.subscribeKeepProgress);
7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356
              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 已提交
7357 7358
    }
  }
7359
  taos_free_result(res);
7360

S
Shengliang Guan 已提交
7361 7362
  for (uint64_t i = pThreadInfo->start_table_from;
          i <= pThreadInfo->end_table_to; i++) {
7363 7364
    tsubSeq = i - pThreadInfo->start_table_from;
    taos_unsubscribe(tsub[tsubSeq], 0);
7365
  }
7366

7367
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
7368 7369 7370
  return NULL;
}

7371 7372
static void *specifiedSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
7373
//  TAOS_SUB*  tsub = NULL;
7374

7375
  if (pThreadInfo->taos == NULL) {
7376
    pThreadInfo->taos = taos_connect(g_queryInfo.host,
7377 7378 7379 7380
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
          g_queryInfo.port);
7381
    if (pThreadInfo->taos == NULL) {
7382
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
7383
            pThreadInfo->threadID, taos_errstr(NULL));
7384 7385 7386 7387
      return NULL;
    }
  }

7388 7389
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
7390 7391
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
7392 7393
    return NULL;
  }
7394

7395 7396 7397 7398
  sprintf(g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID],
          "taosdemo-subscribe-%"PRIu64"-%d",
          pThreadInfo->querySeq,
          pThreadInfo->threadID);
7399
  if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != '\0') {
7400
      sprintf(pThreadInfo->filePath, "%s-%d",
7401 7402 7403
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
  }
7404 7405
  g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID] = subscribeImpl(
          SPECIFIED_CLASS, pThreadInfo,
7406
          g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq],
7407
          g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID],
7408
          g_queryInfo.specifiedQueryInfo.subscribeRestart,
7409
          g_queryInfo.specifiedQueryInfo.subscribeInterval);
7410
  if (NULL == g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]) {
7411 7412
      taos_close(pThreadInfo->taos);
      return NULL;
S
Shengliang Guan 已提交
7413
  }
7414

7415
  // start loop to consume result
7416

7417
  g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] = 0;
7418 7419 7420 7421
  while((g_queryInfo.specifiedQueryInfo.endAfterConsume[pThreadInfo->querySeq] == -1)
          || (g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] <
              g_queryInfo.specifiedQueryInfo.endAfterConsume[pThreadInfo->querySeq])) {

7422
      if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) {
7423 7424
        continue;
      }
7425

7426 7427 7428
      g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID] = taos_consume(
              g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]);
      if (g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID]) {
7429 7430
          if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0]
                  != 0) {
7431
              sprintf(pThreadInfo->filePath, "%s-%d",
7432 7433 7434
                      g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                      pThreadInfo->threadID);
          }
7435 7436 7437
          fetchResult(
                  g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID],
                  pThreadInfo);
7438

7439
          g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] ++;
7440
          if ((g_queryInfo.specifiedQueryInfo.resubAfterConsume[pThreadInfo->querySeq] != -1)
7441
                && (g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] >=
7442 7443 7444 7445
                    g_queryInfo.specifiedQueryInfo.resubAfterConsume[pThreadInfo->querySeq])) {
              printf("keepProgress:%d, resub specified query: %"PRIu64"\n",
                    g_queryInfo.specifiedQueryInfo.subscribeKeepProgress,
                    pThreadInfo->querySeq);
7446 7447
              g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] = 0;
              taos_unsubscribe(g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID],
7448
                      g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
7449 7450 7451 7452 7453 7454 7455 7456
              g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID] =
                  subscribeImpl(
                          SPECIFIED_CLASS,
                          pThreadInfo,
                          g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq],
                          g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID],
                          g_queryInfo.specifiedQueryInfo.subscribeRestart,
                          g_queryInfo.specifiedQueryInfo.subscribeInterval);
7457
              if (NULL == g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]) {
7458 7459
                  taos_close(pThreadInfo->taos);
                  return NULL;
7460 7461
              }
          }
7462 7463
      }
  }
7464 7465
  taos_free_result(g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID]);
  taos_unsubscribe(g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->querySeq], 0);
7466
  taos_close(pThreadInfo->taos);
7467

H
hzcheng 已提交
7468 7469 7470
  return NULL;
}

7471
static int subscribeTestProcess() {
7472
  setupForAnsiEscape();
7473
  printfQueryMeta();
7474
  resetAfterAnsiEscape();
7475

7476
  prompt();
7477

7478 7479 7480 7481 7482
  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
7483
          g_queryInfo.port);
7484
  if (taos == NULL) {
7485 7486
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
7487 7488 7489
    exit(-1);
  }

7490
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
7491 7492
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
7493 7494 7495
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
7496 7497
  }

7498 7499
  taos_close(taos); // TODO: workaround to use separate taos connection;

7500 7501
  pthread_t  *pids = NULL;
  threadInfo *infos = NULL;
7502 7503 7504 7505 7506

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

  //==== create threads for query for specified table
S
Shengliang Guan 已提交
7507
  if (g_queryInfo.specifiedQueryInfo.sqlCount <= 0) {
7508
    debugPrint("%s() LN%d, sepcified query sqlCount %d.\n",
7509
              __func__, __LINE__,
S
Shengliang Guan 已提交
7510 7511 7512
              g_queryInfo.specifiedQueryInfo.sqlCount);
  } else {
    if (g_queryInfo.specifiedQueryInfo.concurrent <= 0) {
7513
        errorPrint("%s() LN%d, sepcified query sqlCount %d.\n",
S
Shengliang Guan 已提交
7514 7515 7516 7517
              __func__, __LINE__,
              g_queryInfo.specifiedQueryInfo.sqlCount);
        exit(-1);
    }
7518

7519 7520 7521 7522 7523 7524 7525 7526
    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 已提交
7527 7528 7529 7530
    if ((NULL == pids) || (NULL == infos)) {
        errorPrint("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__);
        exit(-1);
    }
7531

7532 7533 7534
    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;
7535 7536 7537 7538 7539
            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);
7540
        }
S
Shengliang Guan 已提交
7541
    }
H
hzcheng 已提交
7542
  }
7543

7544 7545
  //==== create threads for super table query
  if (g_queryInfo.superQueryInfo.sqlCount <= 0) {
7546
    debugPrint("%s() LN%d, super table query sqlCount %d.\n",
7547 7548 7549 7550
              __func__, __LINE__,
              g_queryInfo.superQueryInfo.sqlCount);
  } else {
    if ((g_queryInfo.superQueryInfo.sqlCount > 0)
7551
          && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
7552 7553 7554
        pidsOfStable  = malloc(
                g_queryInfo.superQueryInfo.sqlCount *
                g_queryInfo.superQueryInfo.threadCnt *
7555
            sizeof(pthread_t));
7556 7557 7558
        infosOfStable = malloc(
                g_queryInfo.superQueryInfo.sqlCount *
                g_queryInfo.superQueryInfo.threadCnt *
7559
            sizeof(threadInfo));
7560 7561
        if ((NULL == pidsOfStable) || (NULL == infosOfStable)) {
            errorPrint("%s() LN%d, malloc failed for create threads\n",
7562
              __func__, __LINE__);
7563 7564 7565
            // taos_close(taos);
            exit(-1);
        }
7566

7567 7568
        int64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
        int threads = g_queryInfo.superQueryInfo.threadCnt;
7569

7570 7571 7572 7573 7574
        int64_t a = ntables / threads;
        if (a < 1) {
            threads = ntables;
            a = 1;
        }
7575

7576 7577 7578 7579
        int64_t b = 0;
        if (threads != 0) {
            b = ntables % threads;
        }
7580

7581
        for (uint64_t i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
7582
            uint64_t tableFrom = 0;
7583 7584
            for (int j = 0; j < threads; j++) {
                uint64_t seq = i * threads + j;
7585 7586 7587 7588
                threadInfo *pThreadInfo = infosOfStable + seq;
                pThreadInfo->threadID = seq;
                pThreadInfo->querySeq = i;

7589
                pThreadInfo->start_table_from = tableFrom;
7590
                pThreadInfo->ntables = j<b?a+1:a;
7591 7592
                pThreadInfo->end_table_to = j<b?tableFrom+a:tableFrom+a-1;
                tableFrom = pThreadInfo->end_table_to + 1;
7593
                pThreadInfo->taos = NULL; // TODO: workaround to use separate taos connection;
7594
                pthread_create(pidsOfStable + seq,
7595
                        NULL, superSubscribe, pThreadInfo);
7596 7597
            }
        }
7598

7599
        g_queryInfo.superQueryInfo.threadCnt = threads;
7600

7601 7602 7603 7604 7605 7606
        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);
            }
        }
7607
    }
H
hzcheng 已提交
7608
  }
7609

7610 7611 7612 7613 7614
  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);
    }
7615
  }
H
hzcheng 已提交
7616

7617
  tmfree((char*)pids);
7618
  tmfree((char*)infos);
H
hzcheng 已提交
7619

7620 7621
  tmfree((char*)pidsOfStable);
  tmfree((char*)infosOfStable);
7622
//   taos_close(taos);
7623
  return 0;
H
hzcheng 已提交
7624 7625
}

7626
static void initOfInsertMeta() {
7627
  memset(&g_Dbs, 0, sizeof(SDbs));
7628

7629
  // set default values
7630
  tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
7631
  g_Dbs.port = 6030;
7632 7633
  tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
7634
  g_Dbs.threadCount = 2;
7635 7636

  g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
7637 7638
}

7639
static void initOfQueryMeta() {
7640
  memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo));
7641

7642
  // set default values
7643
  tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
7644
  g_queryInfo.port = 6030;
7645 7646
  tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
L
Liu Tao 已提交
7647 7648
}

7649
static void setParaFromArg(){
7650
  if (g_args.host) {
7651
    tstrncpy(g_Dbs.host, g_args.host, MAX_HOSTNAME_SIZE);
7652
  } else {
7653
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
7654
  }
L
Liu Tao 已提交
7655

7656
  if (g_args.user) {
7657
    tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE);
7658
  }
7659 7660

  if (g_args.password) {
7661
    tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE);
7662 7663
  }

7664 7665
  if (g_args.port) {
    g_Dbs.port = g_args.port;
7666
  }
L
Liu Tao 已提交
7667

7668 7669 7670
  g_Dbs.threadCount = g_args.num_of_threads;
  g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;

7671
  g_Dbs.dbCount = 1;
7672
  g_Dbs.db[0].drop = true;
7673

7674
  tstrncpy(g_Dbs.db[0].dbName, g_args.database, TSDB_DB_NAME_LEN);
7675
  g_Dbs.db[0].dbCfg.replica = g_args.replica;
7676
  tstrncpy(g_Dbs.db[0].dbCfg.precision, "ms", 8);
L
Liu Tao 已提交
7677

7678
  tstrncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN);
7679 7680 7681 7682 7683

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

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

7685 7686
  char dataString[STRING_LEN];
  char **data_type = g_args.datatype;
7687

7688
  memset(dataString, 0, STRING_LEN);
L
Liu Tao 已提交
7689

7690 7691
  if (strcasecmp(data_type[0], "BINARY") == 0
          || strcasecmp(data_type[0], "BOOL") == 0
7692
          || strcasecmp(data_type[0], "NCHAR") == 0 ) {
7693
    g_Dbs.do_aggreFunc = false;
L
Liu Tao 已提交
7694
  }
H
hzcheng 已提交
7695

7696 7697
  if (g_args.use_metric) {
    g_Dbs.db[0].superTblCount = 1;
7698
    tstrncpy(g_Dbs.db[0].superTbls[0].sTblName, "meters", TSDB_TABLE_NAME_LEN);
7699 7700
    g_Dbs.db[0].superTbls[0].childTblCount = g_args.num_of_tables;
    g_Dbs.threadCount = g_args.num_of_threads;
7701
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
7702
    g_Dbs.asyncMode = g_args.async_mode;
7703

7704 7705 7706 7707
    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;
7708
    tstrncpy(g_Dbs.db[0].superTbls[0].childTblPrefix,
7709
            g_args.tb_prefix, TSDB_TABLE_NAME_LEN - 20);
7710
    tstrncpy(g_Dbs.db[0].superTbls[0].dataSource, "rand", MAX_TB_NAME_SIZE);
7711
    g_Dbs.db[0].superTbls[0].iface = g_args.iface;
7712
    tstrncpy(g_Dbs.db[0].superTbls[0].startTimestamp,
7713
            "2017-07-14 10:40:00.000", MAX_TB_NAME_SIZE);
7714
    g_Dbs.db[0].superTbls[0].timeStampStep = DEFAULT_TIMESTAMP_STEP;
7715

7716
    g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT;
7717
    g_Dbs.db[0].superTbls[0].maxSqlLen = g_args.max_sql_len;
7718

7719 7720 7721 7722 7723
    g_Dbs.db[0].superTbls[0].columnCount = 0;
    for (int i = 0; i < MAX_NUM_DATATYPE; i++) {
      if (data_type[i] == NULL) {
        break;
      }
7724

7725
      tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
7726
              data_type[i], strlen(data_type[i]) + 1);
7727
      g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary;
7728 7729
      g_Dbs.db[0].superTbls[0].columnCount++;
    }
7730

7731 7732 7733
    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 {
7734 7735 7736
      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,
7737
                "INT", strlen("INT") + 1);
7738
        g_Dbs.db[0].superTbls[0].columns[i].dataLen = 0;
7739 7740 7741
        g_Dbs.db[0].superTbls[0].columnCount++;
      }
    }
7742

7743
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType,
7744
            "INT", strlen("INT") + 1);
7745
    g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0;
7746

7747
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType,
7748
            "BINARY", strlen("BINARY") + 1);
7749 7750
    g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary;
    g_Dbs.db[0].superTbls[0].tagCount = 2;
7751
  } else {
7752 7753
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
    g_Dbs.db[0].superTbls[0].tagCount = 0;
H
hzcheng 已提交
7754
  }
7755 7756 7757 7758 7759 7760
}

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

7762 7763 7764
  /* Compile regular expression */
  if (regcomp(&regex, reg, cflags) != 0) {
    printf("Fail to compile regex\n");
H
Hui Li 已提交
7765 7766 7767
    exit(-1);
  }

7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791
  /* 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);
}

7792
static void querySqlFile(TAOS* taos, char* sqlFile)
7793 7794 7795 7796 7797 7798
{
  FILE *fp = fopen(sqlFile, "r");
  if (fp == NULL) {
    printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno));
    return;
  }
7799

7800 7801 7802 7803 7804 7805
  int       read_len = 0;
  char *    cmd = calloc(1, MAX_SQL_SIZE);
  size_t    cmd_len = 0;
  char *    line = NULL;
  size_t    line_len = 0;

7806
  double t = taosGetTimestampMs();
7807

7808
  while((read_len = tgetline(&line, &line_len, fp)) != -1) {
7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820
    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;
7821
    }
7822 7823

    memcpy(cmd + cmd_len, line, read_len);
7824 7825 7826
    if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE, false)) {
        errorPrint("%s() LN%d, queryDbExec %s failed!\n",
               __func__, __LINE__, cmd);
7827 7828 7829 7830 7831
        tmfree(cmd);
        tmfree(line);
        tmfclose(fp);
        return;
    }
7832 7833
    memset(cmd, 0, MAX_SQL_SIZE);
    cmd_len = 0;
H
hzcheng 已提交
7834 7835
  }

7836
  t = taosGetTimestampMs() - t;
7837
  printf("run %s took %.6f second(s)\n\n", sqlFile, t);
7838

7839 7840 7841 7842
  tmfree(cmd);
  tmfree(line);
  tmfclose(fp);
  return;
H
hzcheng 已提交
7843 7844
}

7845
static void testMetaFile() {
7846
    if (INSERT_TEST == g_args.test_mode) {
7847 7848
      if (g_Dbs.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir);
7849

7850
      insertTestProcess();
7851

7852
    } else if (QUERY_TEST == g_args.test_mode) {
7853 7854
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
7855

7856
      queryTestProcess();
7857

7858
    } else if (SUBSCRIBE_TEST == g_args.test_mode) {
7859 7860
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
7861

7862
      subscribeTestProcess();
7863

7864 7865 7866
    }  else {
      ;
    }
7867
}
7868

7869
static void queryResult() {
7870
  // query data
7871

7872
  pthread_t read_id;
7873 7874 7875 7876
  threadInfo *pThreadInfo = malloc(sizeof(threadInfo));
  assert(pThreadInfo);
  pThreadInfo->start_time = 1500000000000;  // 2017-07-14 10:40:00.000
  pThreadInfo->start_table_from = 0;
7877

7878
  //pThreadInfo->do_aggreFunc = g_Dbs.do_aggreFunc;
7879
  if (g_args.use_metric) {
7880 7881 7882 7883
    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,
7884
          g_Dbs.db[0].superTbls[0].childTblPrefix, TSDB_TABLE_NAME_LEN - 20);
7885
  } else {
7886 7887
    pThreadInfo->ntables = g_args.num_of_tables;
    pThreadInfo->end_table_to = g_args.num_of_tables -1;
7888
    tstrncpy(pThreadInfo->tb_prefix, g_args.tb_prefix, TSDB_TABLE_NAME_LEN);
7889 7890
  }

7891
  pThreadInfo->taos = taos_connect(
7892 7893 7894 7895 7896
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
          g_Dbs.port);
7897
  if (pThreadInfo->taos == NULL) {
7898 7899
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
7900
    free(pThreadInfo);
7901 7902 7903
    exit(-1);
  }

7904
  tstrncpy(pThreadInfo->filePath, g_Dbs.resultFile, MAX_FILE_NAME_LEN);
7905 7906

  if (!g_Dbs.use_metric) {
7907
    pthread_create(&read_id, NULL, readTable, pThreadInfo);
7908
  } else {
7909
    pthread_create(&read_id, NULL, readMetric, pThreadInfo);
7910 7911
  }
  pthread_join(read_id, NULL);
7912 7913
  taos_close(pThreadInfo->taos);
  free(pThreadInfo);
7914 7915
}

7916 7917
static void testCmdLine() {

7918 7919 7920 7921 7922 7923 7924 7925 7926 7927
  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);
  }

7928 7929
  g_args.test_mode = INSERT_TEST;
  insertTestProcess();
7930

7931
  if (false == g_Dbs.insert_only)
7932
    queryResult();
7933 7934
}

7935 7936 7937
int main(int argc, char *argv[]) {
  parse_args(argc, argv, &g_args);

7938
  debugPrint("meta file: %s\n", g_args.metaFile);
7939 7940 7941

  if (g_args.metaFile) {
    initOfInsertMeta();
7942
    initOfQueryMeta();
7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955

    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(
7956 7957 7958 7959
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
7960
          g_Dbs.port);
7961
      querySqlFile(qtaos, g_args.sqlFile);
7962 7963 7964 7965 7966
      taos_close(qtaos);

    } else {
      testCmdLine();
    }
7967 7968 7969

    if (g_dupstr)
        free(g_dupstr);
H
hzcheng 已提交
7970
  }
7971 7972

  return 0;
H
hzcheng 已提交
7973
}
7974