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

16 17 18 19 20

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

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

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

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

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

55 56 57
#define REQ_EXTRA_BUF_LEN   1024
#define RESP_BUF_LEN        4096

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

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

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

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

#define   MAX_SAMPLES_ONCE_FROM_FILE   10000
#define   MAX_NUM_DATATYPE 10

#define   MAX_DB_COUNT           8
89
#define   MAX_SUPER_TABLE_COUNT  200
90 91 92
#define   MAX_COLUMN_COUNT       1024
#define   MAX_TAG_COUNT          128

93
#define   MAX_QUERY_SQL_COUNT    100
94
#define   MAX_QUERY_SQL_LENGTH   1024
95 96

#define   MAX_DATABASE_COUNT     256
97
#define INPUT_BUF_LEN   256
98

99
#define DEFAULT_TIMESTAMP_STEP  1
100

101

102 103 104 105 106
typedef enum CREATE_SUB_TALBE_MOD_EN {
  PRE_CREATE_SUBTBL,
  AUTO_CREATE_SUBTBL,
  NO_CREATE_SUBTBL
} CREATE_SUB_TALBE_MOD_EN;
107

108 109
typedef enum TALBE_EXISTS_EN {
  TBL_NO_EXISTS,
110
  TBL_ALREADY_EXISTS,
111 112 113 114
  TBL_EXISTS_BUTT
} TALBE_EXISTS_EN;

enum MODE {
115 116
  SYNC_MODE,
  ASYNC_MODE,
117 118
  MODE_BUT
};
119

120 121 122 123 124 125
typedef enum enum_INSERT_MODE {
    PROGRESSIVE_INSERT_MODE,
    INTERLACE_INSERT_MODE,
    INVALID_INSERT_MODE
} INSERT_MODE;

126
typedef enum enumQUERY_TYPE {
127
  NO_INSERT_TYPE,
128
  INSERT_TYPE,
129
  QUERY_TYPE_BUT
130
} QUERY_TYPE;
131 132 133 134 135 136 137

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

167 168 169 170 171 172 173 174 175 176 177 178 179 180
enum _describe_table_index {
  TSDB_DESCRIBE_METRIC_FIELD_INDEX,
  TSDB_DESCRIBE_METRIC_TYPE_INDEX,
  TSDB_DESCRIBE_METRIC_LENGTH_INDEX,
  TSDB_DESCRIBE_METRIC_NOTE_INDEX,
  TSDB_MAX_DESCRIBE_METRIC
};

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

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

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

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

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

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

256
  uint32_t     columnCount;
257
  StrColumn    columns[MAX_COLUMN_COUNT];
258
  uint32_t          tagCount;
259 260 261
  StrColumn    tags[MAX_TAG_COUNT];

  char*        childTblName;
262
  char*        colsOfCreateChildTable;
263 264
  uint64_t     lenOfOneRow;
  uint64_t     lenOfTagOfOneRow;
265 266 267 268 269

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

270
  uint32_t     tagSource;    // 0: rand, 1: tag sample
271
  char*        tagDataBuf;
272 273
  uint32_t     tagSampleCount;
  uint32_t     tagUsePos;
274

275
  // statistics
276 277
  uint64_t     totalInsertRows;
  uint64_t     totalAffectedRows;
278 279 280 281 282 283
} SSuperTable;

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

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

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

typedef struct SDbs_S {
329
  char         cfgDir[MAX_FILE_NAME_LEN+1];
330
  char         host[MAX_HOSTNAME_SIZE];
331 332
  struct sockaddr_in serv_addr;

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

342 343 344
  uint32_t     threadCount;
  uint32_t     threadCountByCreateTbl;
  uint32_t     dbCount;
345 346 347
  SDataBase    db[MAX_DB_COUNT];

  // statistics
348 349
  uint64_t     totalInsertRows;
  uint64_t     totalAffectedRows;
350

351 352
} SDbs;

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

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

384
  char*        childTblName;
385
  uint64_t     totalQueried;
386
} SuperQueryInfo;
387 388

typedef struct SQueryMetaInfo_S {
389
  char         cfgDir[MAX_FILE_NAME_LEN+1];
390
  char         host[MAX_HOSTNAME_SIZE];
391
  uint16_t     port;
392
  struct       sockaddr_in serv_addr;
393 394
  char         user[MAX_USERNAME_SIZE];
  char         password[MAX_PASSWORD_SIZE];
395
  char         dbName[MAX_DB_NAME_SIZE+1];
396
  char         queryMode[MAX_TB_NAME_SIZE];  // taosc, rest
397

398 399
  SpecifiedQueryInfo  specifiedQueryInfo;
  SuperQueryInfo    superQueryInfo;
400
  uint64_t     totalQueried;
401 402 403
} SQueryMetaInfo;

typedef struct SThreadInfo_S {
404 405 406 407 408 409 410 411 412 413 414 415 416
  TAOS *    taos;
  int       threadID;
  char      db_name[MAX_DB_NAME_SIZE+1];
  uint32_t  time_precision;
  char      fp[4096];
  char      tb_prefix[MAX_TB_NAME_SIZE];
  uint64_t  start_table_from;
  uint64_t  end_table_to;
  uint64_t  ntables;
  uint64_t  data_of_rate;
  int64_t   start_time;
  char*     cols;
  bool      use_metric;
417 418 419
  SSuperTable* superTblInfo;

  // for async insert
420 421
  tsem_t    lock_sem;
  int64_t   counter;
422 423
  uint64_t  st;
  uint64_t  et;
424
  uint64_t  lastTs;
425

426
  // sample data
427
  int64_t   samplePos;
428
  // statistics
429 430
  uint64_t  totalInsertRows;
  uint64_t  totalAffectedRows;
431 432

  // insert delay statistics
433 434 435 436 437
  uint64_t  cntDelay;
  uint64_t  totalDelay;
  uint64_t  avgDelay;
  uint64_t  maxDelay;
  uint64_t  minDelay;
438

439
  // query
440
  uint64_t  querySeq;   // sequence number of sql command
441 442
} threadInfo;

443
#ifdef WINDOWS
444 445
#define _CRT_RAND_S

446
#include <windows.h>
447 448 449 450 451
#include <winsock2.h>

typedef unsigned __int32 uint32_t;

#pragma comment ( lib, "ws2_32.lib" )
452 453
// Some old MinGW/CYGWIN distributions don't define this:
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
454 455
  #define ENABLE_VIRTUAL_TERMINAL_PROCESSING  0x0004
#endif // ENABLE_VIRTUAL_TERMINAL_PROCESSING
456 457 458 459

static HANDLE g_stdoutHandle;
static DWORD g_consoleMode;

460
static void setupForAnsiEscape(void) {
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
  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());
479
  }
480 481
}

482
static void resetAfterAnsiEscape(void) {
483
  // Reset colors
484
  printf("\x1b[0m");
485 486 487 488 489 490

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

492
static int taosRandom()
493 494 495 496 497 498
{
    int number;
    rand_s(&number);

    return number;
}
499
#else   // Not windows
500
static void setupForAnsiEscape(void) {}
501

502
static void resetAfterAnsiEscape(void) {
503 504 505
  // Reset colors
  printf("\x1b[0m");
}
506

507 508
#include <time.h>

509
static int taosRandom()
510
{
511
  return rand();
512 513
}

514
#endif // ifdef Windows
515

516
static int createDatabasesAndStables();
517
static void createChildTables();
518
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet);
519 520 521 522 523 524 525

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

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

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



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

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

587
#define verbosePrint(fmt, ...) \
588 589
    do { if (g_args.verbose_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)
590

591 592 593 594
#define performancePrint(fmt, ...) \
    do { if (g_args.performance_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)

595 596 597 598
#define errorPrint(fmt, ...) \
    do { fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); } while(0)


599
///////////////////////////////////////////////////
H
hzcheng 已提交
600

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

603 604 605 606 607 608 609 610
#ifndef TAOSDEMO_COMMIT_SHA1
#define TAOSDEMO_COMMIT_SHA1 "unknown"
#endif

#ifndef TD_VERNUMBER
#define TD_VERNUMBER    "unknown"
#endif

611
#ifndef TAOSDEMO_STATUS
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628
#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);
    }
}

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

695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
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;
}

710
static void parse_args(int argc, char *argv[], SArguments *arguments) {
711
  char **sptr;
712 713 714 715 716

  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 已提交
717 718 719 720 721
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-c need a valid path following!\n");
        exit(EXIT_FAILURE);
      }
722
      tstrncpy(configDir, argv[++i], TSDB_FILENAME_LEN);
723

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

929
      arguments->disorderRatio = atoi(argv[++i]);
930

931
      if (arguments->disorderRatio > 50) {
932
        arguments->disorderRatio = 50;
933
      }
934

935
      if (arguments->disorderRatio < 0) {
936
        arguments->disorderRatio = 0;
937
      }
938

939
    } else if (strcmp(argv[i], "-R") == 0) {
940 941 942 943 944 945
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-R need a number following!\n");
        exit(EXIT_FAILURE);
      }
946

947
      arguments->disorderRange = atoi(argv[++i]);
948 949 950
      if (arguments->disorderRange < 0)
        arguments->disorderRange = 1000;

951
    } else if (strcmp(argv[i], "-a") == 0) {
952 953 954 955 956 957
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-a need a number following!\n");
        exit(EXIT_FAILURE);
      }
958 959 960
      arguments->replica = atoi(argv[++i]);
      if (arguments->replica > 3 || arguments->replica < 1) {
          arguments->replica = 1;
961
      }
962 963
    } else if (strcmp(argv[i], "-D") == 0) {
      arguments->method_of_delete = atoi(argv[++i]);
964 965 966
      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 已提交
967
      }
968 969 970 971
    } else if ((strcmp(argv[i], "--version") == 0) ||
        (strcmp(argv[i], "-V") == 0)){
      printVersion();
      exit(0);
972 973 974 975 976
    } else if (strcmp(argv[i], "--help") == 0) {
      printHelp();
      exit(0);
    } else {
      printHelp();
977
      errorPrint("%s", "ERROR: wrong options\n");
978
      exit(EXIT_FAILURE);
S
TD-1057  
Shengliang Guan 已提交
979 980
    }
  }
981

982
  if (((arguments->debug_print) && (arguments->metaFile == NULL))
983
          || arguments->verbose_print) {
984
    printf("###################################################################\n");
985
    printf("# meta file:                         %s\n", arguments->metaFile);
986
    printf("# Server IP:                         %s:%hu\n",
987 988
            arguments->host == NULL ? "localhost" : arguments->host,
            arguments->port );
989 990 991
    printf("# User:                              %s\n", arguments->user);
    printf("# Password:                          %s\n", arguments->password);
    printf("# Use metric:                        %s\n", arguments->use_metric ? "true" : "false");
992
    if (*(arguments->datatype)) {
993 994 995 996 997 998 999
        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");
1000
    }
1001
    printf("# Insertion interval:                %"PRIu64"\n",
1002
            arguments->insert_interval);
1003
    printf("# Number of records per req:         %"PRIu64"\n",
1004
            arguments->num_of_RPR);
1005
    printf("# Max SQL length:                    %"PRIu64"\n",
1006
            arguments->max_sql_len);
1007
    printf("# Length of Binary:                  %d\n", arguments->len_of_binary);
1008
    printf("# Number of Threads:                 %d\n", arguments->num_of_threads);
1009
    printf("# Number of Tables:                  %"PRIu64"\n",
1010
            arguments->num_of_tables);
1011
    printf("# Number of Data per Table:          %"PRIu64"\n",
1012
            arguments->num_of_DPT);
1013 1014 1015 1016 1017
    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);
1018

1019 1020 1021 1022
    }
    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);
1023
    printf("# Print verbose info:                %d\n", arguments->verbose_print);
1024 1025 1026 1027 1028 1029
    printf("###################################################################\n");
    if (!arguments->answer_yes) {
        printf("Press enter key to continue\n\n");
        (void) getchar();
    }
  }
1030
}
H
hzcheng 已提交
1031

1032 1033 1034 1035
static bool getInfoFromJsonFile(char* file);
//static int generateOneRowDataForStb(SSuperTable* stbInfo);
//static int getDataIntoMemForStb(SSuperTable* stbInfo);
static void init_rand_data();
1036
static void tmfclose(FILE *fp) {
1037 1038 1039 1040
  if (NULL != fp) {
    fclose(fp);
  }
}
1041

1042
static void tmfree(char *buf) {
1043 1044
  if (NULL != buf) {
    free(buf);
H
Hui Li 已提交
1045
  }
1046
}
H
Hui Li 已提交
1047

1048
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet) {
1049 1050 1051
  int i;
  TAOS_RES *res = NULL;
  int32_t   code = -1;
1052

1053 1054 1055 1056
  for (i = 0; i < 5; i++) {
    if (NULL != res) {
      taos_free_result(res);
      res = NULL;
H
hzcheng 已提交
1057
    }
1058

1059 1060 1061 1062
    res = taos_query(taos, command);
    code = taos_errno(res);
    if (0 == code) {
      break;
1063
    }
H
hzcheng 已提交
1064 1065
  }

1066
  if (code != 0) {
1067 1068
    if (!quiet) {
      debugPrint("%s() LN%d - command: %s\n", __func__, __LINE__, command);
1069
      errorPrint("Failed to run %s, reason: %s\n", command, taos_errstr(res));
1070
    }
1071 1072 1073
    taos_free_result(res);
    //taos_close(taos);
    return -1;
1074
  }
H
hzcheng 已提交
1075

1076 1077 1078 1079
  if (INSERT_TYPE == type) {
    int affectedRows = taos_affected_rows(res);
    taos_free_result(res);
    return affectedRows;
H
hzcheng 已提交
1080
  }
1081

1082
  taos_free_result(res);
1083 1084
  return 0;
}
H
hzcheng 已提交
1085

1086
static void getResult(TAOS_RES *res, char* resultFileName) {
1087 1088 1089 1090 1091 1092 1093 1094 1095
  TAOS_ROW    row = NULL;
  int         num_rows = 0;
  int         num_fields = taos_field_count(res);
  TAOS_FIELD *fields     = taos_fetch_fields(res);

  FILE *fp = NULL;
  if (resultFileName[0] != 0) {
    fp = fopen(resultFileName, "at");
    if (fp == NULL) {
1096 1097
      errorPrint("%s() LN%d, failed to open result file: %s, result will not save to file\n",
              __func__, __LINE__, resultFileName);
1098 1099
    }
  }
1100

1101 1102
  char* databuf = (char*) calloc(1, 100*1024*1024);
  if (databuf == NULL) {
1103 1104
    errorPrint("%s() LN%d, failed to malloc, warning: save result to file slowly!\n",
            __func__, __LINE__);
1105 1106
    if (fp)
        fclose(fp);
1107 1108
    return ;
  }
H
hzcheng 已提交
1109

1110 1111
  int   totalLen = 0;
  char  temp[16000];
H
hzcheng 已提交
1112

1113
  // fetch the records row by row
1114
  while((row = taos_fetch_row(res))) {
1115 1116 1117 1118
    if (totalLen >= 100*1024*1024 - 32000) {
      if (fp) fprintf(fp, "%s", databuf);
      totalLen = 0;
      memset(databuf, 0, 100*1024*1024);
H
hzcheng 已提交
1119
    }
1120 1121 1122 1123 1124 1125
    num_rows++;
    int len = taos_print_row(temp, row, fields, num_fields);
    len += sprintf(temp + len, "\n");
    //printf("query result:%s\n", temp);
    memcpy(databuf + totalLen, temp, len);
    totalLen += len;
H
hzcheng 已提交
1126 1127
  }

1128 1129 1130 1131
  if (fp) fprintf(fp, "%s", databuf);
  tmfclose(fp);
  free(databuf);
}
H
hzcheng 已提交
1132

1133 1134 1135
static void selectAndGetResult(TAOS *taos, char *command, char* resultFileName) {
  TAOS_RES *res = taos_query(taos, command);
  if (res == NULL || taos_errno(res) != 0) {
1136
    errorPrint("%s() LN%d, failed to execute sql:%s, reason:%s\n",
1137
       __func__, __LINE__, command, taos_errstr(res));
1138 1139
    taos_free_result(res);
    return;
H
hzcheng 已提交
1140
  }
1141

1142 1143 1144
  getResult(res, resultFileName);
  taos_free_result(res);
}
H
hzcheng 已提交
1145

1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184
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;
1185
  return randfloat[cursor];
1186 1187
}

1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
#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

1205
static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1206

1207
static void rand_string(char *str, int size) {
1208 1209 1210 1211
  str[0] = 0;
  if (size > 0) {
    //--size;
    int n;
1212
    for (n = 0; n < size; n++) {
1213
      int key = abs(rand_tinyint()) % (int)(sizeof(charset) - 1);
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229
      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++){
1230 1231 1232 1233
    randint[i] = (int)(taosRandom() % 65535);
    randbigint[i] = (int64_t)(taosRandom() % 2147483648);
    randfloat[i] = (float)(taosRandom() / 1000.0);
    randdouble[i] = (double)(taosRandom() / 1000000.0);
1234 1235 1236
  }
}

1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256
#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)

1257
static int printfInsertMeta() {
1258
    SHOW_PARSE_RESULT_START();
1259

1260 1261 1262
  printf("host:                       \033[33m%s:%u\033[0m\n", g_Dbs.host, g_Dbs.port);
  printf("user:                       \033[33m%s\033[0m\n", g_Dbs.user);
  printf("password:                   \033[33m%s\033[0m\n", g_Dbs.password);
1263
  printf("configDir:                  \033[33m%s\033[0m\n", configDir);
1264 1265 1266
  printf("resultFile:                 \033[33m%s\033[0m\n", g_Dbs.resultFile);
  printf("thread num of insert data:  \033[33m%d\033[0m\n", g_Dbs.threadCount);
  printf("thread num of create table: \033[33m%d\033[0m\n", g_Dbs.threadCountByCreateTbl);
1267
  printf("top insert interval:        \033[33m%"PRIu64"\033[0m\n",
1268
          g_args.insert_interval);
1269
  printf("number of records per req:  \033[33m%"PRIu64"\033[0m\n",
1270
          g_args.num_of_RPR);
1271
  printf("max sql length:             \033[33m%"PRIu64"\033[0m\n",
1272
          g_args.max_sql_len);
1273 1274

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

1276 1277
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    printf("database[\033[33m%d\033[0m]:\n", i);
1278
    printf("  database[%d] name:      \033[33m%s\033[0m\n", i, g_Dbs.db[i].dbName);
1279
    if (0 == g_Dbs.db[i].drop) {
1280 1281 1282
      printf("  drop:                  \033[33mno\033[0m\n");
    } else {
      printf("  drop:                  \033[33myes\033[0m\n");
1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321
    }

    if (g_Dbs.db[i].dbCfg.blocks > 0) {
      printf("  blocks:                \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.blocks);
    }
    if (g_Dbs.db[i].dbCfg.cache > 0) {
      printf("  cache:                 \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.cache);
    }
    if (g_Dbs.db[i].dbCfg.days > 0) {
      printf("  days:                  \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.days);
    }
    if (g_Dbs.db[i].dbCfg.keep > 0) {
      printf("  keep:                  \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.keep);
    }
    if (g_Dbs.db[i].dbCfg.replica > 0) {
      printf("  replica:               \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.replica);
    }
    if (g_Dbs.db[i].dbCfg.update > 0) {
      printf("  update:                \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.update);
    }
    if (g_Dbs.db[i].dbCfg.minRows > 0) {
      printf("  minRows:               \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.minRows);
    }
    if (g_Dbs.db[i].dbCfg.maxRows > 0) {
      printf("  maxRows:               \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.maxRows);
    }
    if (g_Dbs.db[i].dbCfg.comp > 0) {
      printf("  comp:                  \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.comp);
    }
    if (g_Dbs.db[i].dbCfg.walLevel > 0) {
      printf("  walLevel:              \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.walLevel);
    }
    if (g_Dbs.db[i].dbCfg.fsync > 0) {
      printf("  fsync:                 \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.fsync);
    }
    if (g_Dbs.db[i].dbCfg.quorum > 0) {
      printf("  quorum:                \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.quorum);
    }
    if (g_Dbs.db[i].dbCfg.precision[0] != 0) {
1322
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
1323
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1324
        printf("  precision:             \033[33m%s\033[0m\n",
1325
            g_Dbs.db[i].dbCfg.precision);
1326
      } else {
1327
        printf("\033[1m\033[40;31m  precision error:       %s\033[0m\n",
1328
                g_Dbs.db[i].dbCfg.precision);
1329
        return -1;
1330 1331 1332
      }
    }

1333
    printf("  super table count:     \033[33m%"PRIu64"\033[0m\n",
1334
        g_Dbs.db[i].superTblCount);
1335 1336
    for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      printf("  super table[\033[33m%"PRIu64"\033[0m]:\n", j);
1337

1338
      printf("      stbName:           \033[33m%s\033[0m\n",
1339
          g_Dbs.db[i].superTbls[j].sTblName);
1340 1341 1342 1343 1344 1345 1346 1347

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

1349 1350 1351 1352 1353 1354 1355
      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");
      }
1356

1357
      printf("      childTblCount:     \033[33m%"PRIu64"\033[0m\n",
1358
              g_Dbs.db[i].superTbls[j].childTblCount);
1359
      printf("      childTblPrefix:    \033[33m%s\033[0m\n",
1360
              g_Dbs.db[i].superTbls[j].childTblPrefix);
1361
      printf("      dataSource:        \033[33m%s\033[0m\n",
1362
              g_Dbs.db[i].superTbls[j].dataSource);
1363
      printf("      insertMode:        \033[33m%s\033[0m\n",
1364
              g_Dbs.db[i].superTbls[j].insertMode);
1365
      if (g_Dbs.db[i].superTbls[j].childTblLimit > 0) {
1366
        printf("      childTblLimit:     \033[33m%"PRId64"\033[0m\n",
1367
                g_Dbs.db[i].superTbls[j].childTblLimit);
1368
      }
1369
      if (g_Dbs.db[i].superTbls[j].childTblOffset > 0) {
1370
        printf("      childTblOffset:    \033[33m%"PRIu64"\033[0m\n",
1371
                g_Dbs.db[i].superTbls[j].childTblOffset);
1372
      }
1373
      printf("      insertRows:        \033[33m%"PRIu64"\033[0m\n",
1374
              g_Dbs.db[i].superTbls[j].insertRows);
1375
/*
1376
      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1377
        printf("      multiThreadWriteOneTbl:  \033[33mno\033[0m\n");
1378
      }else {
1379
        printf("      multiThreadWriteOneTbl:  \033[33myes\033[0m\n");
1380
      }
1381
      */
1382
      printf("      interlaceRows:     \033[33m%"PRIu64"\033[0m\n",
1383
              g_Dbs.db[i].superTbls[j].interlaceRows);
1384 1385

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

1390
      printf("      disorderRange:     \033[33m%d\033[0m\n",
1391
              g_Dbs.db[i].superTbls[j].disorderRange);
1392
      printf("      disorderRatio:     \033[33m%d\033[0m\n",
1393
              g_Dbs.db[i].superTbls[j].disorderRatio);
1394
      printf("      maxSqlLen:         \033[33m%"PRIu64"\033[0m\n",
1395
              g_Dbs.db[i].superTbls[j].maxSqlLen);
1396
      printf("      timeStampStep:     \033[33m%"PRId64"\033[0m\n",
1397
              g_Dbs.db[i].superTbls[j].timeStampStep);
1398
      printf("      startTimestamp:    \033[33m%s\033[0m\n",
1399
              g_Dbs.db[i].superTbls[j].startTimestamp);
1400
      printf("      sampleFormat:      \033[33m%s\033[0m\n",
1401
              g_Dbs.db[i].superTbls[j].sampleFormat);
1402
      printf("      sampleFile:        \033[33m%s\033[0m\n",
1403
              g_Dbs.db[i].superTbls[j].sampleFile);
1404
      printf("      tagsFile:          \033[33m%s\033[0m\n",
1405
              g_Dbs.db[i].superTbls[j].tagsFile);
1406
      printf("      columnCount:       \033[33m%d\033[0m\n",
1407
              g_Dbs.db[i].superTbls[j].columnCount);
1408 1409
      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);
1410
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType,
1411 1412 1413
                       "binary", 6))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType,
                       "nchar", 5))) {
1414
          printf("column[\033[33m%d\033[0m]:\033[33m%s(%d)\033[0m ", k,
1415 1416
                  g_Dbs.db[i].superTbls[j].columns[k].dataType,
                  g_Dbs.db[i].superTbls[j].columns[k].dataLen);
1417
        } else {
1418
          printf("column[%d]:\033[33m%s\033[0m ", k,
1419
                  g_Dbs.db[i].superTbls[j].columns[k].dataType);
1420 1421 1422
        }
      }
      printf("\n");
1423 1424

      printf("      tagCount:            \033[33m%d\033[0m\n        ",
1425
              g_Dbs.db[i].superTbls[j].tagCount);
1426 1427
      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);
1428
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
1429 1430 1431
                        "binary", strlen("binary")))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                        "nchar", strlen("nchar")))) {
1432
          printf("tag[%d]:\033[33m%s(%d)\033[0m ", k,
1433 1434
                  g_Dbs.db[i].superTbls[j].tags[k].dataType,
                  g_Dbs.db[i].superTbls[j].tags[k].dataLen);
1435
        } else {
1436
          printf("tag[%d]:\033[33m%s\033[0m ", k,
1437
                  g_Dbs.db[i].superTbls[j].tags[k].dataType);
1438
        }
1439 1440 1441 1442 1443
      }
      printf("\n");
    }
    printf("\n");
  }
1444 1445

  SHOW_PARSE_RESULT_END();
1446 1447

  return 0;
1448 1449 1450
}

static void printfInsertMetaToFile(FILE* fp) {
1451 1452

  SHOW_PARSE_RESULT_START_TO_FILE(fp);
1453

1454 1455
  fprintf(fp, "host:                       %s:%u\n", g_Dbs.host, g_Dbs.port);
  fprintf(fp, "user:                       %s\n", g_Dbs.user);
1456
  fprintf(fp, "configDir:                  %s\n", configDir);
1457 1458 1459
  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);
1460 1461
  fprintf(fp, "number of records per req:  %"PRIu64"\n", g_args.num_of_RPR);
  fprintf(fp, "max sql length:             %"PRIu64"\n", g_args.max_sql_len);
1462
  fprintf(fp, "database count:          %d\n", g_Dbs.dbCount);
1463

1464 1465
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    fprintf(fp, "database[%d]:\n", i);
1466
    fprintf(fp, "  database[%d] name:       %s\n", i, g_Dbs.db[i].dbName);
1467
    if (0 == g_Dbs.db[i].drop) {
1468
      fprintf(fp, "  drop:                  no\n");
1469
    }else {
1470
      fprintf(fp, "  drop:                  yes\n");
1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509
    }

    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) {
1510
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
1511
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1512 1513 1514 1515 1516 1517
        fprintf(fp, "  precision:             %s\n", g_Dbs.db[i].dbCfg.precision);
      } else {
        fprintf(fp, "  precision error:       %s\n", g_Dbs.db[i].dbCfg.precision);
      }
    }

1518
    fprintf(fp, "  super table count:     %"PRIu64"\n", g_Dbs.db[i].superTblCount);
1519 1520
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      fprintf(fp, "  super table[%d]:\n", j);
1521 1522

      fprintf(fp, "      stbName:           %s\n",  g_Dbs.db[i].superTbls[j].sTblName);
1523 1524 1525 1526 1527 1528 1529 1530

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

1532 1533 1534 1535 1536 1537 1538
      if (TBL_NO_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
        fprintf(fp, "      childTblExists:    %s\n",  "no");
      } else if (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
        fprintf(fp, "      childTblExists:    %s\n",  "yes");
      } else {
        fprintf(fp, "      childTblExists:    %s\n",  "error");
      }
1539

1540
      fprintf(fp, "      childTblCount:     %"PRIu64"\n",
1541 1542 1543 1544 1545 1546 1547
              g_Dbs.db[i].superTbls[j].childTblCount);
      fprintf(fp, "      childTblPrefix:    %s\n",
              g_Dbs.db[i].superTbls[j].childTblPrefix);
      fprintf(fp, "      dataSource:        %s\n",
              g_Dbs.db[i].superTbls[j].dataSource);
      fprintf(fp, "      insertMode:        %s\n",
              g_Dbs.db[i].superTbls[j].insertMode);
1548
      fprintf(fp, "      insertRows:        %"PRIu64"\n",
1549
              g_Dbs.db[i].superTbls[j].insertRows);
1550
      fprintf(fp, "      interlace rows:    %"PRIu64"\n",
1551
              g_Dbs.db[i].superTbls[j].interlaceRows);
1552
      if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) {
1553
        fprintf(fp, "      stable insert interval:   %"PRIu64"\n",
1554
                g_Dbs.db[i].superTbls[j].insertInterval);
1555
      }
1556
/*
1557
      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1558
        fprintf(fp, "      multiThreadWriteOneTbl:  no\n");
1559
      }else {
1560
        fprintf(fp, "      multiThreadWriteOneTbl:  yes\n");
1561
      }
1562
      */
1563
      fprintf(fp, "      interlaceRows:     %"PRIu64"\n",
1564
              g_Dbs.db[i].superTbls[j].interlaceRows);
1565
      fprintf(fp, "      disorderRange:     %d\n",  g_Dbs.db[i].superTbls[j].disorderRange);
1566
      fprintf(fp, "      disorderRatio:     %d\n",  g_Dbs.db[i].superTbls[j].disorderRatio);
1567
      fprintf(fp, "      maxSqlLen:         %"PRIu64"\n",
1568
              g_Dbs.db[i].superTbls[j].maxSqlLen);
1569

1570 1571 1572 1573
      fprintf(fp, "      timeStampStep:     %"PRId64"\n",
              g_Dbs.db[i].superTbls[j].timeStampStep);
      fprintf(fp, "      startTimestamp:    %s\n",
              g_Dbs.db[i].superTbls[j].startTimestamp);
1574
      fprintf(fp, "      sampleFormat:      %s\n",  g_Dbs.db[i].superTbls[j].sampleFormat);
1575 1576 1577
      fprintf(fp, "      sampleFile:        %s\n",  g_Dbs.db[i].superTbls[j].sampleFile);
      fprintf(fp, "      tagsFile:          %s\n",  g_Dbs.db[i].superTbls[j].tagsFile);

1578 1579 1580
      fprintf(fp, "      columnCount:       %d\n        ",  g_Dbs.db[i].superTbls[j].columnCount);
      for (int k = 0; k < g_Dbs.db[i].superTbls[j].columnCount; k++) {
        //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].columns[k].dataType, g_Dbs.db[i].superTbls[j].columns[k].dataLen);
1581
        if ((0 == strncasecmp(
1582 1583 1584 1585
                        g_Dbs.db[i].superTbls[j].columns[k].dataType,
                        "binary", strlen("binary")))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType,
                        "nchar", strlen("nchar")))) {
1586 1587 1588
          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);
1589 1590 1591 1592 1593
        } else {
          fprintf(fp, "column[%d]:%s ", k, g_Dbs.db[i].superTbls[j].columns[k].dataType);
        }
      }
      fprintf(fp, "\n");
1594 1595 1596

      fprintf(fp, "      tagCount:            %d\n        ",
              g_Dbs.db[i].superTbls[j].tagCount);
1597 1598
      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);
1599
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
1600 1601 1602
                        "binary", strlen("binary")))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                        "nchar", strlen("nchar")))) {
1603 1604
          fprintf(fp, "tag[%d]:%s(%d) ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType,
                  g_Dbs.db[i].superTbls[j].tags[k].dataLen);
1605 1606
        } else {
          fprintf(fp, "tag[%d]:%s ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType);
1607
        }
1608 1609 1610 1611 1612
      }
      fprintf(fp, "\n");
    }
    fprintf(fp, "\n");
  }
1613

1614
  SHOW_PARSE_RESULT_END_TO_FILE(fp);
1615 1616 1617
}

static void printfQueryMeta() {
1618

1619
  SHOW_PARSE_RESULT_START();
1620

1621
  printf("host:                    \033[33m%s:%u\033[0m\n",
1622
          g_queryInfo.host, g_queryInfo.port);
1623 1624 1625 1626
  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");
1627 1628 1629 1630

  if ((SUBSCRIBE_TEST == g_args.test_mode) || (QUERY_TEST == g_args.test_mode)) {
    printf("specified table query info:                   \n");
    printf("sqlCount:       \033[33m%"PRIu64"\033[0m\n",
1631
      g_queryInfo.specifiedQueryInfo.sqlCount);
1632 1633 1634
    if (g_queryInfo.specifiedQueryInfo.sqlCount > 0) {
      printf("specified tbl query times:\n");
      printf("                \033[33m%"PRIu64"\033[0m\n",
1635
      g_queryInfo.specifiedQueryInfo.queryTimes);
1636 1637 1638 1639 1640 1641
      printf("query interval: \033[33m%"PRIu64" ms\033[0m\n",
        g_queryInfo.specifiedQueryInfo.queryInterval);
      printf("top query times:\033[33m%"PRIu64"\033[0m\n", g_args.query_times);
      printf("concurrent:     \033[33m%"PRIu64"\033[0m\n",
      g_queryInfo.specifiedQueryInfo.concurrent);
      printf("mod:            \033[33m%s\033[0m\n",
1642
        (g_queryInfo.specifiedQueryInfo.asyncMode)?"async":"sync");
1643
      printf("interval:       \033[33m%"PRIu64"\033[0m\n",
1644
        g_queryInfo.specifiedQueryInfo.subscribeInterval);
1645
      printf("restart:        \033[33m%d\033[0m\n",
1646
        g_queryInfo.specifiedQueryInfo.subscribeRestart);
1647
      printf("keepProgress:   \033[33m%d\033[0m\n",
1648
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
1649

1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673
      for (uint64_t i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
        printf("  sql[%"PRIu64"]: \033[33m%s\033[0m\n",
            i, g_queryInfo.specifiedQueryInfo.sql[i]);
      }
      printf("\n");
    }

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

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

      printf("mod:            \033[33m%s\033[0m\n",
1674
        (g_queryInfo.superQueryInfo.asyncMode)?"async":"sync");
1675
      printf("interval:       \033[33m%"PRIu64"\033[0m\n",
1676
        g_queryInfo.superQueryInfo.subscribeInterval);
1677
      printf("restart:        \033[33m%d\033[0m\n",
1678
        g_queryInfo.superQueryInfo.subscribeRestart);
1679
      printf("keepProgress:   \033[33m%d\033[0m\n",
1680
        g_queryInfo.superQueryInfo.subscribeKeepProgress);
1681

1682 1683 1684 1685 1686 1687
      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");
    }
1688
  }
1689

1690
  SHOW_PARSE_RESULT_END();
1691 1692
}

1693
static char* formatTimestamp(char* buf, int64_t val, int precision) {
1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724
  time_t tt;
  if (precision == TSDB_TIME_PRECISION_MICRO) {
    tt = (time_t)(val / 1000000);
  } else {
    tt = (time_t)(val / 1000);
  }

/* comment out as it make testcases like select_with_tags.sim fail.
  but in windows, this may cause the call to localtime crash if tt < 0,
  need to find a better solution.
  if (tt < 0) {
    tt = 0;
  }
  */

#ifdef WINDOWS
  if (tt < 0) tt = 0;
#endif

  struct tm* ptm = localtime(&tt);
  size_t pos = strftime(buf, 32, "%Y-%m-%d %H:%M:%S", ptm);

  if (precision == TSDB_TIME_PRECISION_MICRO) {
    sprintf(buf + pos, ".%06d", (int)(val % 1000000));
  } else {
    sprintf(buf + pos, ".%03d", (int)(val % 1000));
  }

  return buf;
}

1725
static void xDumpFieldToFile(FILE* fp, const char* val,
1726
        TAOS_FIELD* field, int32_t length, int precision) {
1727

1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762
  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:
1763
      formatTimestamp(buf, *(int64_t*)val, precision);
1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778
      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) {
1779
    errorPrint("%s() LN%d, failed to open file: %s\n", __func__, __LINE__, fname);
1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793
    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);
1794

1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814
  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;
}

1815 1816
static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) {
  TAOS_RES * res;
1817 1818
  TAOS_ROW row = NULL;
  int count = 0;
1819 1820

  res = taos_query(taos, "show databases;");
1821
  int32_t code = taos_errno(res);
1822

1823
  if (code != 0) {
1824
    errorPrint( "failed to run <show databases>, reason: %s\n", taos_errstr(res));
1825 1826 1827 1828 1829
    return -1;
  }

  TAOS_FIELD *fields = taos_fetch_fields(res);

1830
  while((row = taos_fetch_row(res)) != NULL) {
1831
    // sys database name : 'log'
1832
    if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "log",
1833
                fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) {
1834 1835
      continue;
    }
1836 1837 1838

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

1843
    tstrncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX],
1844
            fields[TSDB_SHOW_DB_NAME_INDEX].bytes);
1845
    formatTimestamp(dbInfos[count]->create_time,
1846 1847
            *(int64_t*)row[TSDB_SHOW_DB_CREATED_TIME_INDEX],
            TSDB_TIME_PRECISION_MILLI);
1848
    dbInfos[count]->ntables = *((int32_t *)row[TSDB_SHOW_DB_NTABLES_INDEX]);
1849
    dbInfos[count]->vgroups = *((int32_t *)row[TSDB_SHOW_DB_VGROUPS_INDEX]);
1850 1851
    dbInfos[count]->replica = *((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX]);
    dbInfos[count]->quorum = *((int16_t *)row[TSDB_SHOW_DB_QUORUM_INDEX]);
1852
    dbInfos[count]->days = *((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]);
1853

1854
    tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX],
1855
            fields[TSDB_SHOW_DB_KEEP_INDEX].bytes);
1856 1857 1858 1859 1860 1861 1862
    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]));
1863
    dbInfos[count]->cachelast =
1864
      (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_CACHELAST_INDEX]));
1865

1866
    tstrncpy(dbInfos[count]->precision,
1867 1868
            (char *)row[TSDB_SHOW_DB_PRECISION_INDEX],
            fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes);
1869
    dbInfos[count]->update = *((int8_t *)row[TSDB_SHOW_DB_UPDATE_INDEX]);
1870
    tstrncpy(dbInfos[count]->status, (char *)row[TSDB_SHOW_DB_STATUS_INDEX],
1871
            fields[TSDB_SHOW_DB_STATUS_INDEX].bytes);
1872

1873 1874
    count++;
    if (count > MAX_DATABASE_COUNT) {
1875
      errorPrint("%s() LN%d, The database count overflow than %d\n",
1876
         __func__, __LINE__, MAX_DATABASE_COUNT);
1877 1878 1879 1880 1881 1882 1883
      break;
    }
  }

  return count;
}

1884
static void printfDbInfoForQueryToFile(
1885
        char* filename, SDbInfo* dbInfos, int index) {
1886

1887
  if (filename[0] == 0)
1888
      return;
1889 1890 1891

  FILE *fp = fopen(filename, "at");
  if (fp == NULL) {
1892
    errorPrint( "failed to open file: %s\n", filename);
1893
    return;
1894 1895 1896 1897 1898 1899
  }

  fprintf(fp, "================ database[%d] ================\n", index);
  fprintf(fp, "name: %s\n", dbInfos->name);
  fprintf(fp, "created_time: %s\n", dbInfos->create_time);
  fprintf(fp, "ntables: %d\n", dbInfos->ntables);
1900
  fprintf(fp, "vgroups: %d\n", dbInfos->vgroups);
1901 1902
  fprintf(fp, "replica: %d\n", dbInfos->replica);
  fprintf(fp, "quorum: %d\n", dbInfos->quorum);
1903 1904
  fprintf(fp, "days: %d\n", dbInfos->days);
  fprintf(fp, "keep0,keep1,keep(D): %s\n", dbInfos->keeplist);
1905 1906 1907 1908 1909 1910 1911
  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);
1912 1913
  fprintf(fp, "cachelast: %d\n", dbInfos->cachelast);
  fprintf(fp, "precision: %s\n", dbInfos->precision);
1914
  fprintf(fp, "update: %d\n", dbInfos->update);
1915
  fprintf(fp, "status: %s\n", dbInfos->status);
1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929
  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);
1930
  snprintf(filename, MAX_QUERY_SQL_LENGTH, "querySystemInfo-%d-%d-%d %d:%d:%d",
1931 1932
          lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min,
          lt->tm_sec);
1933

1934 1935 1936 1937 1938 1939 1940 1941 1942
  // show variables
  res = taos_query(taos, "show variables;");
  //getResult(res, filename);
  xDumpResultToFile(filename, res);

  // show dnodes
  res = taos_query(taos, "show dnodes;");
  xDumpResultToFile(filename, res);
  //getResult(res, filename);
1943

1944 1945 1946 1947
  // show databases
  res = taos_query(taos, "show databases;");
  SDbInfo** dbInfos = (SDbInfo **)calloc(MAX_DATABASE_COUNT, sizeof(SDbInfo *));
  if (dbInfos == NULL) {
1948
    errorPrint("%s() LN%d, failed to allocate memory\n", __func__, __LINE__);
1949 1950 1951
    return;
  }
  int dbCount = getDbFromServer(taos, dbInfos);
1952
  if (dbCount <= 0) {
1953 1954
      free(dbInfos);
      return;
1955
  }
1956 1957

  for (int i = 0; i < dbCount; i++) {
1958
    // printf database info
1959
    printfDbInfoForQueryToFile(filename, dbInfos[i], i);
1960

1961 1962 1963 1964
    // show db.vgroups
    snprintf(buffer, MAX_QUERY_SQL_LENGTH, "show %s.vgroups;", dbInfos[i]->name);
    res = taos_query(taos, buffer);
    xDumpResultToFile(filename, res);
1965

1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976
    // 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);
}

1977
static int postProceSql(char *host, struct sockaddr_in *pServAddr, uint16_t port, char* sqlstr)
1978
{
1979
    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";
1980

1981
    char *url = "/rest/sql";
1982

1983 1984 1985 1986
    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;
1987

1988
    int req_buf_len = strlen(sqlstr) + REQ_EXTRA_BUF_LEN;
1989

1990 1991 1992 1993 1994
    request_buf = malloc(req_buf_len);
    if (NULL == request_buf) {
      errorPrint("%s", "ERROR, cannot allocate memory.\n");
      exit(EXIT_FAILURE);
    }
1995

1996 1997
    char userpass_buf[INPUT_BUF_LEN];
    int mod_table[] = {0, 2, 1};
1998

1999 2000 2001 2002 2003 2004 2005 2006
    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', '+', '/'};
2007

2008 2009 2010 2011
    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);
2012

2013
    char base64_buf[INPUT_BUF_LEN];
2014
#ifdef WINDOWS
2015
    WSADATA wsaData;
2016
    WSAStartup(MAKEWORD(2, 2), &wsaData);
2017 2018
    SOCKET sockfd;
#else
2019
    int sockfd;
2020
#endif
2021 2022
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
2023
#ifdef WINDOWS
2024
        errorPrint( "Could not create socket : %d" , WSAGetLastError());
2025
#endif
2026 2027 2028 2029
        debugPrint("%s() LN%d, sockfd=%d\n", __func__, __LINE__, sockfd);
        free(request_buf);
        ERROR_EXIT("ERROR opening socket");
    }
2030

2031
    int retConn = connect(sockfd, (struct sockaddr *)pServAddr, sizeof(struct sockaddr));
2032 2033 2034 2035 2036
    debugPrint("%s() LN%d connect() return %d\n", __func__, __LINE__, retConn);
    if (retConn < 0) {
        free(request_buf);
        ERROR_EXIT("ERROR connecting");
    }
2037

2038
    memset(base64_buf, 0, INPUT_BUF_LEN);
2039

2040 2041 2042 2043 2044 2045 2046 2047
    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;
2048

2049 2050 2051 2052 2053
      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];
    }
2054

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

2058 2059 2060
    debugPrint("%s() LN%d: auth string base64 encoded: %s\n",
            __func__, __LINE__, base64_buf);
    char *auth = base64_buf;
2061

2062 2063 2064 2065 2066 2067 2068 2069 2070
    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);
2071

2072 2073 2074
    req_str_len = strlen(request_buf);
    sent = 0;
    do {
2075
#ifdef WINDOWS
2076
        bytes = send(sockfd, request_buf + sent, req_str_len - sent, 0);
2077
#else
2078
        bytes = write(sockfd, request_buf + sent, req_str_len - sent);
2079
#endif
2080 2081 2082 2083 2084 2085
        if (bytes < 0)
            ERROR_EXIT("ERROR writing message to socket");
        if (bytes == 0)
            break;
        sent+=bytes;
    } while(sent < req_str_len);
2086

2087 2088 2089 2090
    memset(response_buf, 0, RESP_BUF_LEN);
    resp_len = sizeof(response_buf) - 1;
    received = 0;
    do {
2091
#ifdef WINDOWS
2092
        bytes = recv(sockfd, response_buf + received, resp_len - received, 0);
2093
#else
2094
        bytes = read(sockfd, response_buf + received, resp_len - received);
2095
#endif
2096 2097 2098 2099 2100 2101 2102 2103
        if (bytes < 0) {
            free(request_buf);
            ERROR_EXIT("ERROR reading response from socket");
        }
        if (bytes == 0)
            break;
        received += bytes;
    } while(received < resp_len);
2104

2105 2106 2107 2108
    if (received == resp_len) {
        free(request_buf);
        ERROR_EXIT("ERROR storing complete response from socket");
    }
H
Haojun Liao 已提交
2109

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

2113
    free(request_buf);
2114
#ifdef WINDOWS
2115
    closesocket(sockfd);
2116 2117
    WSACleanup();
#else
2118
    close(sockfd);
2119
#endif
2120

2121
    return 0;
2122 2123
}

2124
static char* getTagValueFromTagSample(SSuperTable* stbInfo, int tagUsePos) {
2125 2126
  char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
  if (NULL == dataBuf) {
2127
    errorPrint("%s() LN%d, calloc failed! size:%d\n",
2128
        __func__, __LINE__, TSDB_MAX_SQL_LEN+1);
2129 2130
    return NULL;
  }
2131

2132
  int    dataLen = 0;
2133
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2134
          "(%s)", stbInfo->tagDataBuf + stbInfo->lenOfTagOfOneRow * tagUsePos);
2135

2136 2137 2138
  return dataBuf;
}

2139
static char* generateTagVaulesForStb(SSuperTable* stbInfo, int32_t tableSeq) {
2140 2141 2142 2143 2144 2145 2146 2147 2148
  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++) {
2149
    if ((0 == strncasecmp(stbInfo->tags[i].dataType, "binary", strlen("binary")))
2150
            || (0 == strncasecmp(stbInfo->tags[i].dataType, "nchar", strlen("nchar")))) {
2151
      if (stbInfo->tags[i].dataLen > TSDB_MAX_BINARY_LEN) {
2152
        printf("binary or nchar length overflow, max size:%u\n",
2153
                (uint32_t)TSDB_MAX_BINARY_LEN);
2154 2155 2156
        tmfree(dataBuf);
        return NULL;
      }
2157

2158 2159
      int tagBufLen = stbInfo->tags[i].dataLen + 1;
      char* buf = (char*)calloc(tagBufLen, 1);
2160 2161 2162 2163 2164
      if (NULL == buf) {
        printf("calloc failed! size:%d\n", stbInfo->tags[i].dataLen);
        tmfree(dataBuf);
        return NULL;
      }
2165 2166 2167 2168 2169 2170 2171

      if (tableSeq % 2) {
        tstrncpy(buf, "beijing", tagBufLen);
      } else {
        tstrncpy(buf, "shanghai", tagBufLen);
      }
      //rand_string(buf, stbInfo->tags[i].dataLen);
2172
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2173
              "\'%s\', ", buf);
2174
      tmfree(buf);
2175
    } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2176
                "int", strlen("int"))) {
2177
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2178
              "%d, ", tableSeq);
2179
    } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2180
                "bigint", strlen("bigint"))) {
2181
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2182
              "%"PRId64", ", rand_bigint());
2183
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2184
                "float", strlen("float"))) {
2185
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2186
              "%f, ", rand_float());
2187
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2188
                "double", strlen("double"))) {
2189
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2190
              "%f, ", rand_double());
2191
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2192
                "smallint", strlen("smallint"))) {
2193
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2194
              "%d, ", rand_smallint());
2195
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2196
                "tinyint", strlen("tinyint"))) {
2197
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2198
              "%d, ", rand_tinyint());
2199
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2200
                "bool", strlen("bool"))) {
2201
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2202
              "%d, ", rand_bool());
2203
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2204
                "timestamp", strlen("timestamp"))) {
2205
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2206
              "%"PRId64", ", rand_bigint());
2207 2208 2209 2210 2211 2212
    }  else {
      printf("No support data type: %s\n", stbInfo->tags[i].dataType);
      tmfree(dataBuf);
      return NULL;
    }
  }
2213

2214
  dataLen -= 2;
2215
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")");
2216 2217 2218
  return dataBuf;
}

2219
static int calcRowLen(SSuperTable*  superTbls) {
2220 2221
  int colIndex;
  int  lenOfOneRow = 0;
2222

2223 2224
  for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) {
    char* dataType = superTbls->columns[colIndex].dataType;
2225

2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241
    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;
2242
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2243
      lenOfOneRow += 42;
2244
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257
      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;
2258

2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274
    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;
2275
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2276 2277 2278 2279 2280 2281 2282 2283
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 42;
    } else {
      printf("get error tag type : %s\n", dataType);
      exit(-1);
    }
  }

  superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow;
2284

2285 2286 2287 2288
  return 0;
}


2289
static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos,
2290
        char* dbName, char* sTblName, char** childTblNameOfSuperTbl,
2291
        uint64_t* childTblCountOfSuperTbl, int64_t limit, uint64_t offset) {
2292

2293
  char command[BUFFER_SIZE] = "\0";
2294 2295
  char limitBuf[100] = "\0";

2296
  TAOS_RES * res;
2297 2298 2299
  TAOS_ROW row = NULL;

  char* childTblName = *childTblNameOfSuperTbl;
2300 2301

  if (offset >= 0) {
2302
    snprintf(limitBuf, 100, " limit %"PRId64" offset %"PRIu64"",
2303
            limit, offset);
2304 2305
  }

2306
  //get all child table name use cmd: select tbname from superTblName;
2307
  snprintf(command, BUFFER_SIZE, "select tbname from %s.%s %s",
2308
          dbName, sTblName, limitBuf);
2309

2310
  res = taos_query(taos, command);
2311 2312 2313 2314
  int32_t code = taos_errno(res);
  if (code != 0) {
    taos_free_result(res);
    taos_close(taos);
2315
    errorPrint("%s() LN%d, failed to run command %s\n",
2316
           __func__, __LINE__, command);
2317 2318 2319
    exit(-1);
  }

2320
  int childTblCount = (limit < 0)?10000:limit;
2321
  int count = 0;
2322 2323 2324
  if (childTblName == NULL) {
    childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (NULL ==  childTblName) {
2325 2326 2327 2328
    taos_free_result(res);
        taos_close(taos);
        errorPrint("%s() LN%d, failed to allocate memory!\n", __func__, __LINE__);
        exit(-1);
2329 2330 2331
    }
  }

2332
  char* pTblName = childTblName;
2333
  while((row = taos_fetch_row(res)) != NULL) {
2334
    int32_t* len = taos_fetch_lengths(res);
2335
    tstrncpy(pTblName, (char *)row[0], len[0]+1);
2336 2337 2338
    //printf("==== sub table name: %s\n", pTblName);
    count++;
    if (count >= childTblCount - 1) {
2339
      char *tmp = realloc(childTblName,
2340
              (size_t)childTblCount*1.5*TSDB_TABLE_NAME_LEN+1);
2341 2342 2343
      if (tmp != NULL) {
        childTblName = tmp;
        childTblCount = (int)(childTblCount*1.5);
2344
        memset(childTblName + count*TSDB_TABLE_NAME_LEN, 0,
2345
                (size_t)((childTblCount-count)*TSDB_TABLE_NAME_LEN));
2346 2347
      } else {
        // exit, if allocate more memory failed
2348
        errorPrint("%s() LN%d, realloc fail for save child table name of %s.%s\n",
2349
               __func__, __LINE__, dbName, sTblName);
2350 2351 2352 2353 2354 2355
        tmfree(childTblName);
        taos_free_result(res);
        taos_close(taos);
        exit(-1);
      }
    }
2356
    pTblName = childTblName + count * TSDB_TABLE_NAME_LEN;
2357
  }
2358

2359 2360 2361 2362 2363 2364 2365
  *childTblCountOfSuperTbl = count;
  *childTblNameOfSuperTbl  = childTblName;

  taos_free_result(res);
  return 0;
}

2366
static int getAllChildNameOfSuperTable(TAOS * taos, char* dbName,
2367
        char* sTblName, char** childTblNameOfSuperTbl,
2368
        uint64_t* childTblCountOfSuperTbl) {
2369

2370 2371
    return getChildNameOfSuperTableWithLimitAndOffset(taos, dbName, sTblName,
            childTblNameOfSuperTbl, childTblCountOfSuperTbl,
2372
            -1, 0);
2373 2374
}

2375
static int getSuperTableFromServer(TAOS * taos, char* dbName,
2376
        SSuperTable*  superTbls) {
2377

2378
  char command[BUFFER_SIZE] = "\0";
2379
  TAOS_RES * res;
2380 2381
  TAOS_ROW row = NULL;
  int count = 0;
2382

2383
  //get schema use cmd: describe superTblName;
2384
  snprintf(command, BUFFER_SIZE, "describe %s.%s", dbName, superTbls->sTblName);
2385
  res = taos_query(taos, command);
2386 2387 2388
  int32_t code = taos_errno(res);
  if (code != 0) {
    printf("failed to run command %s\n", command);
2389
    taos_free_result(res);
2390 2391 2392 2393 2394 2395
    return -1;
  }

  int tagIndex = 0;
  int columnIndex = 0;
  TAOS_FIELD *fields = taos_fetch_fields(res);
2396
  while((row = taos_fetch_row(res)) != NULL) {
2397 2398 2399
    if (0 == count) {
      count++;
      continue;
2400
    }
2401 2402

    if (strcmp((char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX], "TAG") == 0) {
2403
      tstrncpy(superTbls->tags[tagIndex].field,
2404 2405
              (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
              fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
2406
      tstrncpy(superTbls->tags[tagIndex].dataType,
2407 2408
              (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes);
2409 2410 2411
      superTbls->tags[tagIndex].dataLen =
          *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
      tstrncpy(superTbls->tags[tagIndex].note,
2412 2413
              (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes);
2414
      tagIndex++;
2415
    } else {
2416
      tstrncpy(superTbls->columns[columnIndex].field,
2417 2418
              (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
              fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
2419
      tstrncpy(superTbls->columns[columnIndex].dataType,
2420 2421
              (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes);
2422 2423 2424
      superTbls->columns[columnIndex].dataLen =
          *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
      tstrncpy(superTbls->columns[columnIndex].note,
2425 2426
              (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes);
2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437
      columnIndex++;
    }
    count++;
  }

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

  calcRowLen(superTbls);

2438
/*
2439
  if (TBL_ALREADY_EXISTS == superTbls->childTblExists) {
2440
    //get all child table name use cmd: select tbname from superTblName;
2441 2442 2443
    int childTblCount = 10000;
    superTbls->childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (superTbls->childTblName == NULL) {
2444
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
2445 2446
      return -1;
    }
2447
    getAllChildNameOfSuperTable(taos, dbName,
2448 2449 2450
            superTbls->sTblName,
            &superTbls->childTblName,
            &superTbls->childTblCount);
2451
  }
2452
  */
2453 2454 2455
  return 0;
}

H
Haojun Liao 已提交
2456
static int createSuperTable(
2457 2458
        TAOS * taos, char* dbName,
        SSuperTable*  superTbl) {
H
Haojun Liao 已提交
2459

2460
  char command[BUFFER_SIZE] = "\0";
2461

2462 2463 2464 2465 2466
  char cols[STRING_LEN] = "\0";
  int colIndex;
  int len = 0;

  int  lenOfOneRow = 0;
2467 2468 2469

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

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

2477
    if (strcasecmp(dataType, "BINARY") == 0) {
2478
      len += snprintf(cols + len, STRING_LEN - len,
2479 2480
          ", col%d %s(%d)", colIndex, "BINARY",
          superTbl->columns[colIndex].dataLen);
2481
      lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
2482
    } else if (strcasecmp(dataType, "NCHAR") == 0) {
2483
      len += snprintf(cols + len, STRING_LEN - len,
2484 2485
          ", col%d %s(%d)", colIndex, "NCHAR",
          superTbl->columns[colIndex].dataLen);
2486
      lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504
    } 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;
2505
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2506 2507
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "DOUBLE");
      lenOfOneRow += 42;
2508
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2509 2510 2511 2512
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "TIMESTAMP");
      lenOfOneRow += 21;
    } else {
      taos_close(taos);
2513
      errorPrint("%s() LN%d, config error data type : %s\n",
2514
         __func__, __LINE__, dataType);
2515 2516 2517 2518
      exit(-1);
    }
  }

2519 2520
  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);
2521 2522

  // save for creating child table
2523 2524 2525
  superTbl->colsOfCreateChildTable = (char*)calloc(len+20, 1);
  if (NULL == superTbl->colsOfCreateChildTable) {
    errorPrint("%s() LN%d, Failed when calloc, size:%d",
2526
           __func__, __LINE__, len+1);
2527 2528 2529 2530
    taos_close(taos);
    exit(-1);
  }

2531
  snprintf(superTbl->colsOfCreateChildTable, len+20, "(ts timestamp%s)", cols);
2532
  verbosePrint("%s() LN%d: %s\n",
2533
      __func__, __LINE__, superTbl->colsOfCreateChildTable);
2534

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

2541 2542 2543
  char tags[STRING_LEN] = "\0";
  int tagIndex;
  len = 0;
2544

2545 2546 2547 2548
  int lenOfTagOfOneRow = 0;
  len += snprintf(tags + len, STRING_LEN - len, "(");
  for (tagIndex = 0; tagIndex < superTbl->tagCount; tagIndex++) {
    char* dataType = superTbl->tags[tagIndex].dataType;
2549

2550 2551
    if (strcasecmp(dataType, "BINARY") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
2552
              "BINARY", superTbl->tags[tagIndex].dataLen);
2553 2554 2555
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "NCHAR") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
2556
              "NCHAR", superTbl->tags[tagIndex].dataLen);
2557 2558 2559
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "INT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2560
              "INT");
2561 2562 2563
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 11;
    } else if (strcasecmp(dataType, "BIGINT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2564
              "BIGINT");
2565 2566 2567
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 21;
    } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2568
              "SMALLINT");
2569 2570 2571
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 6;
    } else if (strcasecmp(dataType, "TINYINT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2572
              "TINYINT");
2573 2574 2575
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 4;
    } else if (strcasecmp(dataType, "BOOL") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2576
              "BOOL");
2577 2578 2579
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 6;
    } else if (strcasecmp(dataType, "FLOAT") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2580
              "FLOAT");
2581 2582 2583
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 22;
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2584
              "DOUBLE");
2585 2586 2587
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 42;
    } else {
      taos_close(taos);
2588
      errorPrint("%s() LN%d, config error tag type : %s\n",
2589
         __func__, __LINE__, dataType);
2590
      exit(-1);
2591 2592
    }
  }
2593 2594 2595 2596 2597 2598 2599

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

  superTbl->lenOfTagOfOneRow = lenOfTagOfOneRow;

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

  if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2605 2606 2607
      errorPrint( "create supertable %s failed!\n\n",
              superTbl->sTblName);
      return -1;
2608 2609
  }
  debugPrint("create supertable %s success!\n\n", superTbl->sTblName);
2610 2611 2612
  return 0;
}

2613
static int createDatabasesAndStables() {
2614 2615 2616 2617
  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) {
2618
    errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL));
2619
    return -1;
2620 2621 2622
  }
  char command[BUFFER_SIZE] = "\0";

2623
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2624 2625
    if (g_Dbs.db[i].drop) {
      sprintf(command, "drop database if exists %s;", g_Dbs.db[i].dbName);
2626
      verbosePrint("%s() %d command: %s\n", __func__, __LINE__, command);
2627
      if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2628 2629 2630 2631
        taos_close(taos);
        return -1;
      }

2632
      int dataLen = 0;
2633
      dataLen += snprintf(command + dataLen,
2634
          BUFFER_SIZE - dataLen, "create database if not exists %s", g_Dbs.db[i].dbName);
2635

2636 2637
      if (g_Dbs.db[i].dbCfg.blocks > 0) {
        dataLen += snprintf(command + dataLen,
2638
            BUFFER_SIZE - dataLen, " blocks %d", g_Dbs.db[i].dbCfg.blocks);
2639 2640 2641
      }
      if (g_Dbs.db[i].dbCfg.cache > 0) {
        dataLen += snprintf(command + dataLen,
2642
            BUFFER_SIZE - dataLen, " cache %d", g_Dbs.db[i].dbCfg.cache);
2643 2644 2645
      }
      if (g_Dbs.db[i].dbCfg.days > 0) {
        dataLen += snprintf(command + dataLen,
2646
            BUFFER_SIZE - dataLen, " days %d", g_Dbs.db[i].dbCfg.days);
2647 2648 2649
      }
      if (g_Dbs.db[i].dbCfg.keep > 0) {
        dataLen += snprintf(command + dataLen,
2650
            BUFFER_SIZE - dataLen, " keep %d", g_Dbs.db[i].dbCfg.keep);
2651 2652 2653
      }
      if (g_Dbs.db[i].dbCfg.quorum > 1) {
        dataLen += snprintf(command + dataLen,
2654
            BUFFER_SIZE - dataLen, " quorum %d", g_Dbs.db[i].dbCfg.quorum);
2655 2656 2657
      }
      if (g_Dbs.db[i].dbCfg.replica > 0) {
        dataLen += snprintf(command + dataLen,
2658
            BUFFER_SIZE - dataLen, " replica %d", g_Dbs.db[i].dbCfg.replica);
2659 2660 2661
      }
      if (g_Dbs.db[i].dbCfg.update > 0) {
        dataLen += snprintf(command + dataLen,
2662
            BUFFER_SIZE - dataLen, " update %d", g_Dbs.db[i].dbCfg.update);
2663 2664 2665 2666 2667 2668 2669
      }
      //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,
2670
            BUFFER_SIZE - dataLen, " minrows %d", g_Dbs.db[i].dbCfg.minRows);
2671 2672 2673
      }
      if (g_Dbs.db[i].dbCfg.maxRows > 0) {
        dataLen += snprintf(command + dataLen,
2674
            BUFFER_SIZE - dataLen, " maxrows %d", g_Dbs.db[i].dbCfg.maxRows);
2675 2676 2677
      }
      if (g_Dbs.db[i].dbCfg.comp > 0) {
        dataLen += snprintf(command + dataLen,
2678
            BUFFER_SIZE - dataLen, " comp %d", g_Dbs.db[i].dbCfg.comp);
2679 2680 2681
      }
      if (g_Dbs.db[i].dbCfg.walLevel > 0) {
        dataLen += snprintf(command + dataLen,
2682
            BUFFER_SIZE - dataLen, " wal %d", g_Dbs.db[i].dbCfg.walLevel);
2683 2684 2685
      }
      if (g_Dbs.db[i].dbCfg.cacheLast > 0) {
        dataLen += snprintf(command + dataLen,
2686
            BUFFER_SIZE - dataLen, " cachelast %d", g_Dbs.db[i].dbCfg.cacheLast);
2687 2688 2689
      }
      if (g_Dbs.db[i].dbCfg.fsync > 0) {
        dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
2690
                " fsync %d", g_Dbs.db[i].dbCfg.fsync);
2691 2692
      }
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", strlen("ms")))
2693 2694
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision,
                      "us", strlen("us")))) {
2695
        dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
2696
                " precision \'%s\';", g_Dbs.db[i].dbCfg.precision);
2697 2698 2699 2700 2701 2702 2703 2704 2705
      }

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

2708
    debugPrint("%s() LN%d supertbl count:%"PRIu64"\n",
2709
            __func__, __LINE__, g_Dbs.db[i].superTblCount);
2710 2711 2712

    int validStbCount = 0;

2713
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
2714 2715 2716 2717 2718 2719 2720
      sprintf(command, "describe %s.%s;", g_Dbs.db[i].dbName,
              g_Dbs.db[i].superTbls[j].sTblName);
      verbosePrint("%s() %d command: %s\n", __func__, __LINE__, command);

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

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

2724
        if (0 != ret) {
2725 2726
          errorPrint("create super table %d failed!\n\n", j);
          continue;
2727 2728 2729
        }
      }

2730
      ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName,
2731
                &g_Dbs.db[i].superTbls[j]);
2732 2733
      if (0 != ret) {
        errorPrint("\nget super table %s.%s info failed!\n\n",
2734
                g_Dbs.db[i].dbName, g_Dbs.db[i].superTbls[j].sTblName);
2735
        continue;
2736
      }
2737 2738

      validStbCount ++;
2739
    }
2740 2741

    g_Dbs.db[i].superTblCount = validStbCount;
2742 2743 2744 2745 2746 2747
  }

  taos_close(taos);
  return 0;
}

2748 2749
static void* createTable(void *sarg)
{
2750 2751
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
2752 2753 2754

  int64_t  lastPrintTime = taosGetTimestampMs();

2755
  int buff_len;
2756
  buff_len = BUFFER_SIZE / 8;
2757

2758
  char *buffer = calloc(buff_len, 1);
2759
  if (buffer == NULL) {
2760
    errorPrint("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__);
2761 2762
    exit(-1);
  }
2763 2764 2765

  int len = 0;
  int batchNum = 0;
2766

2767
  verbosePrint("%s() LN%d: Creating table from %"PRIu64" to %"PRIu64"\n",
2768 2769
          __func__, __LINE__,
          pThreadInfo->start_table_from, pThreadInfo->end_table_to);
2770

2771
  for (uint64_t i = pThreadInfo->start_table_from;
2772
          i <= pThreadInfo->end_table_to; i++) {
2773
    if (0 == g_Dbs.use_metric) {
2774
      snprintf(buffer, buff_len,
2775
              "create table if not exists %s.%s%"PRIu64" %s;",
2776 2777 2778
              pThreadInfo->db_name,
              g_args.tb_prefix, i,
              pThreadInfo->cols);
2779
    } else {
2780 2781
      if (superTblInfo == NULL) {
        errorPrint("%s() LN%d, use metric, but super table info is NULL\n",
2782
                  __func__, __LINE__);
2783
        free(buffer);
2784 2785 2786 2787 2788 2789
        exit(-1);
      } else {
        if (0 == len) {
          batchNum = 0;
          memset(buffer, 0, buff_len);
          len += snprintf(buffer + len,
2790
                  buff_len - len, "create table ");
2791 2792 2793
        }
        char* tagsValBuf = NULL;
        if (0 == superTblInfo->tagSource) {
2794
          tagsValBuf = generateTagVaulesForStb(superTblInfo, i);
2795 2796
        } else {
          tagsValBuf = getTagValueFromTagSample(
2797 2798
                  superTblInfo,
                  i % superTblInfo->tagSampleCount);
2799 2800 2801 2802 2803 2804
        }
        if (NULL == tagsValBuf) {
          free(buffer);
          return NULL;
        }
        len += snprintf(buffer + len,
2805
                buff_len - len,
2806
                "if not exists %s.%s%"PRIu64" using %s.%s tags %s ",
2807 2808 2809
                pThreadInfo->db_name, superTblInfo->childTblPrefix,
                i, pThreadInfo->db_name,
                superTblInfo->sTblName, tagsValBuf);
2810 2811 2812
        free(tagsValBuf);
        batchNum++;
        if ((batchNum < superTblInfo->batchCreateTableNum)
2813 2814
                && ((buff_len - len)
                    >= (superTblInfo->lenOfTagOfOneRow + 256))) {
2815 2816
          continue;
        }
2817 2818 2819 2820
      }
    }

    len = 0;
2821
    verbosePrint("%s() LN%d %s\n", __func__, __LINE__, buffer);
2822
    if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)){
2823
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2824
      free(buffer);
2825 2826 2827 2828 2829
      return NULL;
    }

    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
2830
      printf("thread[%d] already create %"PRIu64" - %"PRIu64" tables\n",
2831
              pThreadInfo->threadID, pThreadInfo->start_table_from, i);
2832 2833 2834
      lastPrintTime = currentPrintTime;
    }
  }
2835

2836
  if (0 != len) {
2837
    verbosePrint("%s() %d buffer: %s\n", __func__, __LINE__, buffer);
2838
    if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)) {
2839
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2840
    }
2841
  }
2842

2843 2844 2845 2846
  free(buffer);
  return NULL;
}

2847
static int startMultiThreadCreateChildTable(
2848
        char* cols, int threads, uint64_t startFrom, uint64_t ntables,
2849
        char* db_name, SSuperTable* superTblInfo) {
2850

2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862
  pthread_t *pids = malloc(threads * sizeof(pthread_t));
  threadInfo *infos = malloc(threads * sizeof(threadInfo));

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

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

2863
  uint64_t a = ntables / threads;
2864 2865 2866 2867 2868
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

2869
  uint64_t b = 0;
2870
  b = ntables % threads;
2871

2872
  for (int64_t i = 0; i < threads; i++) {
2873 2874
    threadInfo *t_info = infos + i;
    t_info->threadID = i;
H
Hui Li 已提交
2875
    tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE);
2876
    t_info->superTblInfo = superTblInfo;
2877
    verbosePrint("%s() %d db_name: %s\n", __func__, __LINE__, db_name);
2878
    t_info->taos = taos_connect(
2879 2880 2881 2882 2883
            g_Dbs.host,
            g_Dbs.user,
            g_Dbs.password,
            db_name,
            g_Dbs.port);
2884
    if (t_info->taos == NULL) {
2885
      errorPrint( "%s() LN%d, Failed to connect to TDengine, reason:%s\n",
2886
         __func__, __LINE__, taos_errstr(NULL));
2887
      free(pids);
2888
      free(infos);
2889 2890
      return -1;
    }
2891 2892 2893 2894 2895

    t_info->start_table_from = startFrom;
    t_info->ntables = i<b?a+1:a;
    t_info->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
    startFrom = t_info->end_table_to + 1;
2896
    t_info->use_metric = true;
2897
    t_info->cols = cols;
2898
    t_info->minDelay = UINT64_MAX;
2899 2900
    pthread_create(pids + i, NULL, createTable, t_info);
  }
2901

2902 2903 2904 2905 2906 2907 2908 2909 2910 2911
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

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

  free(pids);
2912
  free(infos);
2913 2914

  return 0;
2915 2916
}

2917
static void createChildTables() {
2918 2919
    char tblColsBuf[MAX_SQL_SIZE];
    int len;
2920

2921
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2922 2923
    if (g_Dbs.use_metric) {
      if (g_Dbs.db[i].superTblCount > 0) {
2924
          // with super table
2925 2926
        for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
          if ((AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable)
2927
                || (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists)) {
2928 2929
            continue;
          }
2930

2931
          verbosePrint("%s() LN%d: %s\n", __func__, __LINE__,
2932
                  g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
2933 2934 2935 2936
          int startFrom = 0;
          g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount;

          verbosePrint("%s() LN%d: create %d child tables from %d\n",
2937
                  __func__, __LINE__, g_totalChildTables, startFrom);
2938
          startMultiThreadCreateChildTable(
2939 2940 2941 2942 2943
                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]));
2944
        }
2945 2946
      }
    } else {
2947 2948
      // normal table
      len = snprintf(tblColsBuf, MAX_SQL_SIZE, "(TS TIMESTAMP");
H
Haojun Liao 已提交
2949
      for (int j = 0; j < g_args.num_of_CPR; j++) {
2950 2951 2952 2953 2954 2955 2956 2957 2958 2959
          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);
2960
      }
2961

2962
      snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ")");
2963

2964
      verbosePrint("%s() LN%d: dbName: %s num of tb: %"PRIu64" schema: %s\n",
2965 2966
              __func__, __LINE__,
              g_Dbs.db[i].dbName, g_args.num_of_tables, tblColsBuf);
2967
      startMultiThreadCreateChildTable(
2968 2969 2970 2971 2972 2973
            tblColsBuf,
            g_Dbs.threadCountByCreateTbl,
            0,
            g_args.num_of_tables,
            g_Dbs.db[i].dbName,
            NULL);
2974
    }
2975 2976 2977 2978 2979 2980
  }
}

/*
  Read 10000 lines at most. If more than 10000 lines, continue to read after using
*/
2981
static int readTagFromCsvFileToMem(SSuperTable  * superTblInfo) {
2982 2983 2984
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
2985

2986 2987
  FILE *fp = fopen(superTblInfo->tagsFile, "r");
  if (fp == NULL) {
2988
    printf("Failed to open tags file: %s, reason:%s\n",
2989
            superTblInfo->tagsFile, strerror(errno));
2990 2991 2992 2993 2994 2995 2996
    return -1;
  }

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

2998 2999 3000 3001 3002 3003 3004 3005 3006
  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;
  }

3007
  while((readLen = tgetline(&line, &n, fp)) != -1) {
3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019
    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) {
3020
      char *tmp = realloc(tagDataBuf,
3021
              (size_t)tagCount*1.5*superTblInfo->lenOfTagOfOneRow);
3022 3023 3024
      if (tmp != NULL) {
        tagDataBuf = tmp;
        tagCount = (int)(tagCount*1.5);
3025
        memset(tagDataBuf + count*superTblInfo->lenOfTagOfOneRow,
3026
                0, (size_t)((tagCount-count)*superTblInfo->lenOfTagOfOneRow));
3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053
      } else {
        // exit, if allocate more memory failed
        printf("realloc fail for save tag val from %s\n", superTblInfo->tagsFile);
        tmfree(tagDataBuf);
        free(line);
        fclose(fp);
        return -1;
      }
    }
  }

  superTblInfo->tagDataBuf = tagDataBuf;
  superTblInfo->tagSampleCount = count;

  free(line);
  fclose(fp);
  return 0;
}

int readSampleFromJsonFileToMem(SSuperTable  * superTblInfo) {
  // TODO
  return 0;
}

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

3061 3062
  FILE*  fp = fopen(superTblInfo->sampleFile, "r");
  if (fp == NULL) {
3063 3064 3065
      errorPrint( "Failed to open sample file: %s, reason:%s\n",
              superTblInfo->sampleFile, strerror(errno));
      return -1;
3066
  }
3067

3068
  assert(superTblInfo->sampleDataBuf);
3069
  memset(superTblInfo->sampleDataBuf, 0,
3070
          MAX_SAMPLES_ONCE_FROM_FILE * superTblInfo->lenOfOneRow);
3071
  while(1) {
3072
    readLen = tgetline(&line, &n, fp);
3073 3074
    if (-1 == readLen) {
      if(0 != fseek(fp, 0, SEEK_SET)) {
3075
        errorPrint( "Failed to fseek file: %s, reason:%s\n",
3076
                superTblInfo->sampleFile, strerror(errno));
3077
        fclose(fp);
3078 3079 3080 3081
        return -1;
      }
      continue;
    }
3082

3083 3084 3085 3086 3087 3088 3089 3090 3091
    if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
      line[--readLen] = 0;
    }

    if (readLen == 0) {
      continue;
    }

    if (readLen > superTblInfo->lenOfOneRow) {
3092
      printf("sample row len[%d] overflow define schema len[%"PRIu64"], so discard this row\n",
3093
              (int32_t)readLen, superTblInfo->lenOfOneRow);
3094 3095 3096
      continue;
    }

3097
    memcpy(superTblInfo->sampleDataBuf + getRows * superTblInfo->lenOfOneRow,
3098
          line, readLen);
3099 3100 3101 3102 3103 3104 3105
    getRows++;

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

3106
  fclose(fp);
3107 3108 3109 3110
  tmfree(line);
  return 0;
}

3111
static bool getColumnAndTagTypeFromInsertJsonFile(
3112
        cJSON* stbInfo, SSuperTable* superTbls) {
3113
  bool  ret = false;
3114

3115
  // columns
3116 3117
  cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns");
  if (columns && columns->type != cJSON_Array) {
3118
    printf("ERROR: failed to read json, columns not found\n");
3119 3120 3121 3122 3123 3124
    goto PARSE_OVER;
  } else if (NULL == columns) {
    superTbls->columnCount = 0;
    superTbls->tagCount    = 0;
    return true;
  }
3125

3126
  int columnSize = cJSON_GetArraySize(columns);
3127
  if ((columnSize + 1/* ts */) > MAX_COLUMN_COUNT) {
3128
    errorPrint("%s() LN%d, failed to read json, column size overflow, max column size is %d\n",
3129
            __func__, __LINE__, MAX_COLUMN_COUNT);
3130 3131 3132 3133 3134 3135
    goto PARSE_OVER;
  }

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

3137
  //superTbls->columnCount = columnSize;
3138 3139 3140 3141 3142 3143 3144
  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) {
3145
      count = countObj->valueint;
3146
    } else if (countObj && countObj->type != cJSON_Number) {
3147
      errorPrint("%s() LN%d, failed to read json, column count not found\n",
3148
          __func__, __LINE__);
3149 3150 3151 3152 3153
      goto PARSE_OVER;
    } else {
      count = 1;
    }

3154
    // column info
3155 3156
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(column, "type");
3157 3158 3159
    if (!dataType || dataType->type != cJSON_String
        || dataType->valuestring == NULL) {
      errorPrint("%s() LN%d: failed to read json, column type not found\n",
3160
          __func__, __LINE__);
3161 3162
      goto PARSE_OVER;
    }
3163 3164
    //tstrncpy(superTbls->columns[k].dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
    tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
3165

3166 3167
    cJSON* dataLen = cJSON_GetObjectItem(column, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3168
      columnCase.dataLen = dataLen->valueint;
3169
    } else if (dataLen && dataLen->type != cJSON_Number) {
3170
      debugPrint("%s() LN%d: failed to read json, column len not found\n",
3171
          __func__, __LINE__);
3172 3173 3174 3175
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 8;
    }
3176

3177
    for (int n = 0; n < count; ++n) {
3178
      tstrncpy(superTbls->columns[index].dataType,
3179
              columnCase.dataType, MAX_TB_NAME_SIZE);
3180
      superTbls->columns[index].dataLen = columnCase.dataLen;
3181 3182
      index++;
    }
3183
  }
3184

3185 3186
  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",
3187
            __func__, __LINE__, MAX_COLUMN_COUNT);
3188 3189 3190
    goto PARSE_OVER;
  }

3191
  superTbls->columnCount = index;
3192

3193 3194
  count = 1;
  index = 0;
3195
  // tags
3196 3197
  cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags");
  if (!tags || tags->type != cJSON_Array) {
3198
    errorPrint("%s() LN%d, failed to read json, tags not found\n",
3199
        __func__, __LINE__);
3200 3201
    goto PARSE_OVER;
  }
3202

3203 3204
  int tagSize = cJSON_GetArraySize(tags);
  if (tagSize > MAX_TAG_COUNT) {
3205
    errorPrint("%s() LN%d, failed to read json, tags size overflow, max tag size is %d\n",
3206
        __func__, __LINE__, MAX_TAG_COUNT);
3207 3208
    goto PARSE_OVER;
  }
3209 3210

  //superTbls->tagCount = tagSize;
3211 3212 3213
  for (int k = 0; k < tagSize; ++k) {
    cJSON* tag = cJSON_GetArrayItem(tags, k);
    if (tag == NULL) continue;
3214

3215 3216 3217
    count = 1;
    cJSON* countObj = cJSON_GetObjectItem(tag, "count");
    if (countObj && countObj->type == cJSON_Number) {
3218
      count = countObj->valueint;
3219
    } else if (countObj && countObj->type != cJSON_Number) {
3220
      printf("ERROR: failed to read json, column count not found\n");
3221 3222 3223 3224 3225
      goto PARSE_OVER;
    } else {
      count = 1;
    }

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

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

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

  if (index > MAX_TAG_COUNT) {
3257
    errorPrint("%s() LN%d, failed to read json, tags size overflow, allowed max tag count is %d\n",
3258
        __func__, __LINE__, MAX_TAG_COUNT);
3259 3260 3261
    goto PARSE_OVER;
  }

3262 3263
  superTbls->tagCount = index;

3264 3265
  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",
3266
        __func__, __LINE__, MAX_COLUMN_COUNT);
3267 3268
    goto PARSE_OVER;
  }
3269 3270
  ret = true;

3271
PARSE_OVER:
3272 3273 3274 3275 3276 3277 3278 3279
  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) {
3280
    tstrncpy(g_Dbs.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3281 3282 3283 3284
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
3285
    tstrncpy(g_Dbs.host, host->valuestring, MAX_HOSTNAME_SIZE);
3286
  } else if (!host) {
3287
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
3288
  } else {
3289
    printf("ERROR: failed to read json, host not found\n");
3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301
    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) {
3302
    tstrncpy(g_Dbs.user, user->valuestring, MAX_USERNAME_SIZE);
3303
  } else if (!user) {
3304
    tstrncpy(g_Dbs.user, "root", MAX_USERNAME_SIZE);
3305 3306 3307 3308
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
3309
    tstrncpy(g_Dbs.password, password->valuestring, MAX_PASSWORD_SIZE);
3310
  } else if (!password) {
3311
    tstrncpy(g_Dbs.password, "taosdata", MAX_PASSWORD_SIZE);
3312 3313 3314 3315
  }

  cJSON* resultfile = cJSON_GetObjectItem(root, "result_file");
  if (resultfile && resultfile->type == cJSON_String && resultfile->valuestring != NULL) {
3316
    tstrncpy(g_Dbs.resultFile, resultfile->valuestring, MAX_FILE_NAME_LEN);
3317
  } else if (!resultfile) {
3318
    tstrncpy(g_Dbs.resultFile, "./insert_res.txt", MAX_FILE_NAME_LEN);
3319 3320 3321 3322 3323 3324 3325 3326
  }

  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 {
3327
    printf("ERROR: failed to read json, threads not found\n");
3328
    goto PARSE_OVER;
3329 3330
  }

3331 3332 3333 3334
  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 已提交
3335
    g_Dbs.threadCountByCreateTbl = 1;
3336
  } else {
3337
    errorPrint("%s() LN%d, failed to read json, threads2 not found\n",
3338
            __func__, __LINE__);
3339
    goto PARSE_OVER;
3340
  }
3341

3342 3343
  cJSON* gInsertInterval = cJSON_GetObjectItem(root, "insert_interval");
  if (gInsertInterval && gInsertInterval->type == cJSON_Number) {
3344 3345 3346 3347 3348
    if (gInsertInterval->valueint <0) {
      errorPrint("%s() LN%d, failed to read json, insert interval input mistake\n",
            __func__, __LINE__);
      goto PARSE_OVER;
    }
3349 3350 3351 3352
    g_args.insert_interval = gInsertInterval->valueint;
  } else if (!gInsertInterval) {
    g_args.insert_interval = 0;
  } else {
3353
    errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
3354
        __func__, __LINE__);
3355 3356
    goto PARSE_OVER;
  }
3357

3358 3359
  cJSON* interlaceRows = cJSON_GetObjectItem(root, "interlace_rows");
  if (interlaceRows && interlaceRows->type == cJSON_Number) {
3360 3361 3362 3363 3364 3365
    if (interlaceRows->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;

    }
3366
    g_args.interlace_rows = interlaceRows->valueint;
3367 3368 3369

    // rows per table need be less than insert batch
    if (g_args.interlace_rows > g_args.num_of_RPR) {
3370
      printf("NOTICE: interlace rows value %"PRIu64" > num_of_records_per_req %"PRIu64"\n\n",
3371
              g_args.interlace_rows, g_args.num_of_RPR);
3372
      printf("        interlace rows value will be set to num_of_records_per_req %"PRIu64"\n\n",
3373
              g_args.num_of_RPR);
3374
      printf("        press Enter key to continue or Ctrl-C to stop.");
3375 3376 3377
      (void)getchar();
      g_args.interlace_rows = g_args.num_of_RPR;
    }
3378
  } else if (!interlaceRows) {
3379
    g_args.interlace_rows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
3380
  } else {
3381
    errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
3382
        __func__, __LINE__);
3383
    goto PARSE_OVER;
3384
  }
3385

3386 3387
  cJSON* maxSqlLen = cJSON_GetObjectItem(root, "max_sql_len");
  if (maxSqlLen && maxSqlLen->type == cJSON_Number) {
3388 3389 3390 3391 3392
    if (maxSqlLen->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;
    }
3393 3394
    g_args.max_sql_len = maxSqlLen->valueint;
  } else if (!maxSqlLen) {
sangshuduo's avatar
sangshuduo 已提交
3395
    g_args.max_sql_len = (1024*1024);
3396
  } else {
3397
    errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
3398
        __func__, __LINE__);
3399 3400 3401 3402 3403
    goto PARSE_OVER;
  }

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

3418
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
3419
  if (answerPrompt
3420 3421
          && answerPrompt->type == cJSON_String
          && answerPrompt->valuestring != NULL) {
3422 3423 3424 3425 3426 3427 3428 3429 3430 3431
    if (0 == strncasecmp(answerPrompt->valuestring, "yes", 3)) {
      g_args.answer_yes = false;
    } else if (0 == strncasecmp(answerPrompt->valuestring, "no", 2)) {
      g_args.answer_yes = true;
    } else {
      g_args.answer_yes = false;
    }
  } else if (!answerPrompt) {
    g_args.answer_yes = false;
  } else {
3432
    printf("ERROR: failed to read json, confirm_parameter_prompt not found\n");
3433
    goto PARSE_OVER;
3434
  }
3435 3436 3437

  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (!dbs || dbs->type != cJSON_Array) {
3438
    printf("ERROR: failed to read json, databases not found\n");
3439 3440 3441 3442 3443
    goto PARSE_OVER;
  }

  int dbSize = cJSON_GetArraySize(dbs);
  if (dbSize > MAX_DB_COUNT) {
3444
    errorPrint(
3445 3446
            "ERROR: failed to read json, databases size overflow, max database is %d\n",
            MAX_DB_COUNT);
3447 3448 3449 3450 3451 3452 3453 3454
    goto PARSE_OVER;
  }

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

3455
    // dbinfo
3456 3457
    cJSON *dbinfo = cJSON_GetObjectItem(dbinfos, "dbinfo");
    if (!dbinfo || dbinfo->type != cJSON_Object) {
3458
      printf("ERROR: failed to read json, dbinfo not found\n");
3459 3460
      goto PARSE_OVER;
    }
3461

3462 3463
    cJSON *dbName = cJSON_GetObjectItem(dbinfo, "name");
    if (!dbName || dbName->type != cJSON_String || dbName->valuestring == NULL) {
3464
      printf("ERROR: failed to read json, db name not found\n");
3465 3466
      goto PARSE_OVER;
    }
3467
    tstrncpy(g_Dbs.db[i].dbName, dbName->valuestring, MAX_DB_NAME_SIZE);
3468 3469 3470

    cJSON *drop = cJSON_GetObjectItem(dbinfo, "drop");
    if (drop && drop->type == cJSON_String && drop->valuestring != NULL) {
3471 3472
      if (0 == strncasecmp(drop->valuestring, "yes", strlen("yes"))) {
        g_Dbs.db[i].drop = true;
3473
      } else {
3474
        g_Dbs.db[i].drop = false;
3475
      }
3476
    } else if (!drop) {
3477
      g_Dbs.db[i].drop = g_args.drop_database;
3478
    } else {
3479
      errorPrint("%s() LN%d, failed to read json, drop input mistake\n",
3480
              __func__, __LINE__);
3481 3482 3483 3484
      goto PARSE_OVER;
    }

    cJSON *precision = cJSON_GetObjectItem(dbinfo, "precision");
3485
    if (precision && precision->type == cJSON_String
3486
            && precision->valuestring != NULL) {
3487
      tstrncpy(g_Dbs.db[i].dbCfg.precision, precision->valuestring,
3488
              MAX_DB_NAME_SIZE);
3489
    } else if (!precision) {
3490
      //tstrncpy(g_Dbs.db[i].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
3491 3492
      memset(g_Dbs.db[i].dbCfg.precision, 0, MAX_DB_NAME_SIZE);
    } else {
3493
      printf("ERROR: failed to read json, precision not found\n");
3494 3495 3496 3497 3498 3499 3500 3501 3502
      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 {
3503
      printf("ERROR: failed to read json, update not found\n");
3504 3505 3506 3507 3508 3509 3510 3511 3512
      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 {
3513
      printf("ERROR: failed to read json, replica not found\n");
3514 3515 3516 3517 3518 3519 3520 3521 3522
      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 {
3523 3524
     printf("ERROR: failed to read json, keep not found\n");
     goto PARSE_OVER;
3525
    }
3526

3527 3528 3529 3530 3531 3532
    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 {
3533 3534
     printf("ERROR: failed to read json, days not found\n");
     goto PARSE_OVER;
3535
    }
3536

3537 3538 3539 3540 3541 3542
    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 {
3543 3544
     printf("ERROR: failed to read json, cache not found\n");
     goto PARSE_OVER;
3545
    }
3546

3547 3548 3549 3550 3551 3552
    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 {
3553 3554
     printf("ERROR: failed to read json, block not found\n");
     goto PARSE_OVER;
3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570
    }

    //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) {
3571
      g_Dbs.db[i].dbCfg.minRows = 0;    // 0 means default
3572
    } else {
3573 3574
     printf("ERROR: failed to read json, minRows not found\n");
     goto PARSE_OVER;
3575 3576 3577 3578 3579 3580
    }

    cJSON* maxRows= cJSON_GetObjectItem(dbinfo, "maxRows");
    if (maxRows && maxRows->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.maxRows = maxRows->valueint;
    } else if (!maxRows) {
3581
      g_Dbs.db[i].dbCfg.maxRows = 0;    // 0 means default
3582
    } else {
3583 3584
     printf("ERROR: failed to read json, maxRows not found\n");
     goto PARSE_OVER;
3585 3586 3587 3588 3589 3590 3591 3592
    }

    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 {
3593 3594
     printf("ERROR: failed to read json, comp not found\n");
     goto PARSE_OVER;
3595 3596 3597 3598 3599 3600 3601 3602
    }

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

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

3617 3618 3619 3620
    cJSON* quorum= cJSON_GetObjectItem(dbinfo, "quorum");
    if (quorum && quorum->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.quorum = quorum->valueint;
    } else if (!quorum) {
3621
      g_Dbs.db[i].dbCfg.quorum = 1;
3622
    } else {
3623 3624
     printf("failed to read json, quorum input mistake");
     goto PARSE_OVER;
3625 3626 3627 3628 3629 3630 3631 3632
    }

    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 {
3633
      errorPrint("%s() LN%d, failed to read json, fsync input mistake\n",
3634
              __func__, __LINE__);
3635
      goto PARSE_OVER;
3636
    }
3637

3638
    // super_talbes
3639 3640
    cJSON *stables = cJSON_GetObjectItem(dbinfos, "super_tables");
    if (!stables || stables->type != cJSON_Array) {
3641
      errorPrint("%s() LN%d, failed to read json, super_tables not found\n",
3642
              __func__, __LINE__);
3643
      goto PARSE_OVER;
3644 3645
    }

3646 3647
    int stbSize = cJSON_GetArraySize(stables);
    if (stbSize > MAX_SUPER_TABLE_COUNT) {
3648
      errorPrint(
3649 3650
              "%s() LN%d, failed to read json, supertable size overflow, max supertable is %d\n",
              __func__, __LINE__, MAX_SUPER_TABLE_COUNT);
3651 3652 3653 3654 3655 3656 3657
      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;
3658 3659

      // dbinfo
3660 3661
      cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name");
      if (!stbName || stbName->type != cJSON_String || stbName->valuestring == NULL) {
3662
        errorPrint("%s() LN%d, failed to read json, stb name not found\n",
3663
                __func__, __LINE__);
3664 3665
        goto PARSE_OVER;
      }
3666
      tstrncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring, MAX_TB_NAME_SIZE);
3667

3668 3669
      cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix");
      if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) {
3670
        printf("ERROR: failed to read json, childtable_prefix not found\n");
3671 3672
        goto PARSE_OVER;
      }
3673
      tstrncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring, MAX_DB_NAME_SIZE);
3674 3675

      cJSON *autoCreateTbl = cJSON_GetObjectItem(stbInfo, "auto_create_table"); // yes, no, null
3676
      if (autoCreateTbl
3677 3678
              && autoCreateTbl->type == cJSON_String
              && autoCreateTbl->valuestring != NULL) {
3679 3680 3681 3682 3683 3684 3685 3686 3687 3688
        if (0 == strncasecmp(autoCreateTbl->valuestring, "yes", 3)) {
          g_Dbs.db[i].superTbls[j].autoCreateTable = AUTO_CREATE_SUBTBL;
        } else if (0 == strncasecmp(autoCreateTbl->valuestring, "no", 2)) {
          g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL;
        } else {
          g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL;
        }
      } else if (!autoCreateTbl) {
        g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL;
      } else {
3689
        printf("ERROR: failed to read json, auto_create_table not found\n");
3690 3691
        goto PARSE_OVER;
      }
3692

3693 3694 3695 3696
      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) {
3697
        g_Dbs.db[i].superTbls[j].batchCreateTableNum = 1000;
3698
      } else {
3699
        printf("ERROR: failed to read json, batch_create_tbl_num not found\n");
3700
        goto PARSE_OVER;
3701
      }
3702 3703

      cJSON *childTblExists = cJSON_GetObjectItem(stbInfo, "child_table_exists"); // yes, no
3704
      if (childTblExists
3705 3706
              && childTblExists->type == cJSON_String
              && childTblExists->valuestring != NULL) {
3707 3708
        if ((0 == strncasecmp(childTblExists->valuestring, "yes", 3))
            && (g_Dbs.db[i].drop == false)) {
3709
          g_Dbs.db[i].superTbls[j].childTblExists = TBL_ALREADY_EXISTS;
3710
        } else if ((0 == strncasecmp(childTblExists->valuestring, "no", 2)
3711
              || (g_Dbs.db[i].drop == true))) {
3712 3713 3714 3715 3716 3717 3718
          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 {
3719
        errorPrint("%s() LN%d, failed to read json, child_table_exists not found\n",
3720
                __func__, __LINE__);
3721 3722
        goto PARSE_OVER;
      }
3723

3724 3725
      cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count");
      if (!count || count->type != cJSON_Number || 0 >= count->valueint) {
3726
        errorPrint("%s() LN%d, failed to read json, childtable_count input mistake\n",
3727
                __func__, __LINE__);
3728 3729 3730 3731 3732
        goto PARSE_OVER;
      }
      g_Dbs.db[i].superTbls[j].childTblCount = count->valueint;

      cJSON *dataSource = cJSON_GetObjectItem(stbInfo, "data_source");
3733
      if (dataSource && dataSource->type == cJSON_String
3734
              && dataSource->valuestring != NULL) {
3735
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource,
3736
                dataSource->valuestring, MAX_DB_NAME_SIZE);
3737
      } else if (!dataSource) {
3738
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource, "rand", MAX_DB_NAME_SIZE);
3739
      } else {
3740
        errorPrint("%s() LN%d, failed to read json, data_source not found\n",
3741
            __func__, __LINE__);
3742 3743 3744
        goto PARSE_OVER;
      }

3745
      cJSON *insertMode = cJSON_GetObjectItem(stbInfo, "insert_mode"); // taosc , rest
3746
      if (insertMode && insertMode->type == cJSON_String
3747
              && insertMode->valuestring != NULL) {
3748
        tstrncpy(g_Dbs.db[i].superTbls[j].insertMode,
3749
                insertMode->valuestring, MAX_DB_NAME_SIZE);
3750
      } else if (!insertMode) {
3751
        tstrncpy(g_Dbs.db[i].superTbls[j].insertMode, "taosc", MAX_DB_NAME_SIZE);
3752
      } else {
3753
        printf("ERROR: failed to read json, insert_mode not found\n");
3754 3755 3756
        goto PARSE_OVER;
      }

3757
      cJSON* childTbl_limit = cJSON_GetObjectItem(stbInfo, "childtable_limit");
3758 3759
      if ((childTbl_limit) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
3760
        if (childTbl_limit->type != cJSON_Number) {
3761 3762
            printf("ERROR: failed to read json, childtable_limit\n");
            goto PARSE_OVER;
3763 3764 3765
        }
        g_Dbs.db[i].superTbls[j].childTblLimit = childTbl_limit->valueint;
      } else {
3766
        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.
3767 3768 3769
      }

      cJSON* childTbl_offset = cJSON_GetObjectItem(stbInfo, "childtable_offset");
3770 3771
      if ((childTbl_offset) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
3772
        if (childTbl_offset->type != cJSON_Number || 0 > childTbl_offset->valueint) {
3773 3774
            printf("ERROR: failed to read json, childtable_offset\n");
            goto PARSE_OVER;
3775 3776 3777 3778 3779 3780
        }
        g_Dbs.db[i].superTbls[j].childTblOffset = childTbl_offset->valueint;
      } else {
        g_Dbs.db[i].superTbls[j].childTblOffset = 0;
      }

3781 3782
      cJSON *ts = cJSON_GetObjectItem(stbInfo, "start_timestamp");
      if (ts && ts->type == cJSON_String && ts->valuestring != NULL) {
3783
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
3784
                ts->valuestring, MAX_DB_NAME_SIZE);
3785
      } else if (!ts) {
3786
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
3787
                "now", MAX_DB_NAME_SIZE);
3788
      } else {
3789
        printf("ERROR: failed to read json, start_timestamp not found\n");
3790 3791
        goto PARSE_OVER;
      }
3792

3793 3794 3795 3796
      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) {
3797
        g_Dbs.db[i].superTbls[j].timeStampStep = DEFAULT_TIMESTAMP_STEP;
3798
      } else {
3799
        printf("ERROR: failed to read json, timestamp_step not found\n");
3800 3801 3802 3803
        goto PARSE_OVER;
      }

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

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

3827 3828
      cJSON *tagsFile = cJSON_GetObjectItem(stbInfo, "tags_file");
      if (tagsFile && tagsFile->type == cJSON_String && tagsFile->valuestring != NULL) {
3829
        tstrncpy(g_Dbs.db[i].superTbls[j].tagsFile,
3830
                tagsFile->valuestring, MAX_FILE_NAME_LEN);
3831 3832 3833 3834 3835 3836 3837 3838 3839
        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 {
3840
        printf("ERROR: failed to read json, tags_file not found\n");
3841 3842
        goto PARSE_OVER;
      }
3843

3844 3845 3846 3847 3848
      cJSON* maxSqlLen = cJSON_GetObjectItem(stbInfo, "max_sql_len");
      if (maxSqlLen && maxSqlLen->type == cJSON_Number) {
        int32_t len = maxSqlLen->valueint;
        if (len > TSDB_MAX_ALLOWED_SQL_LEN) {
          len = TSDB_MAX_ALLOWED_SQL_LEN;
3849 3850
        } else if (len < 5) {
          len = 5;
3851
        }
3852 3853
        g_Dbs.db[i].superTbls[j].maxSqlLen = len;
      } else if (!maxSqlLen) {
3854
        g_Dbs.db[i].superTbls[j].maxSqlLen = g_args.max_sql_len;
3855
      } else {
3856
        errorPrint("%s() LN%d, failed to read json, maxSqlLen input mistake\n",
3857
            __func__, __LINE__);
3858
        goto PARSE_OVER;
3859
      }
3860
/*
3861 3862 3863 3864 3865
      cJSON *multiThreadWriteOneTbl =
          cJSON_GetObjectItem(stbInfo, "multi_thread_write_one_tbl"); // no , yes
      if (multiThreadWriteOneTbl
              && multiThreadWriteOneTbl->type == cJSON_String
              && multiThreadWriteOneTbl->valuestring != NULL) {
3866 3867 3868 3869
        if (0 == strncasecmp(multiThreadWriteOneTbl->valuestring, "yes", 3)) {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 1;
        } else {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
3870
        }
3871 3872 3873
      } else if (!multiThreadWriteOneTbl) {
        g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
      } else {
3874
        printf("ERROR: failed to read json, multiThreadWriteOneTbl not found\n");
3875 3876
        goto PARSE_OVER;
      }
3877
*/
3878 3879
      cJSON* interlaceRows = cJSON_GetObjectItem(stbInfo, "interlace_rows");
      if (interlaceRows && interlaceRows->type == cJSON_Number) {
3880 3881 3882 3883 3884
        if (interlaceRows->valueint < 0) {
          errorPrint("%s() LN%d, failed to read json, interlace rows input mistake\n",
            __func__, __LINE__);
          goto PARSE_OVER;
        }
3885
        g_Dbs.db[i].superTbls[j].interlaceRows = interlaceRows->valueint;
3886 3887
        // rows per table need be less than insert batch
        if (g_Dbs.db[i].superTbls[j].interlaceRows > g_args.num_of_RPR) {
3888
          printf("NOTICE: db[%d].superTbl[%d]'s interlace rows value %"PRIu64" > num_of_records_per_req %"PRIu64"\n\n",
3889
                  i, j, g_Dbs.db[i].superTbls[j].interlaceRows, g_args.num_of_RPR);
3890
          printf("        interlace rows value will be set to num_of_records_per_req %"PRIu64"\n\n",
3891
                  g_args.num_of_RPR);
3892
          printf("        press Enter key to continue or Ctrl-C to stop.");
3893 3894 3895
          (void)getchar();
          g_Dbs.db[i].superTbls[j].interlaceRows = g_args.num_of_RPR;
        }
3896 3897
      } else if (!interlaceRows) {
        g_Dbs.db[i].superTbls[j].interlaceRows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
3898
      } else {
3899
        errorPrint(
3900 3901
                "%s() LN%d, failed to read json, interlace rows input mistake\n",
                __func__, __LINE__);
3902
        goto PARSE_OVER;
3903
      }
3904 3905 3906

      cJSON* disorderRatio = cJSON_GetObjectItem(stbInfo, "disorder_ratio");
      if (disorderRatio && disorderRatio->type == cJSON_Number) {
3907 3908 3909 3910 3911 3912
        if (disorderRatio->valueint > 50)
          disorderRatio->valueint = 50;

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

3913 3914 3915 3916
        g_Dbs.db[i].superTbls[j].disorderRatio = disorderRatio->valueint;
      } else if (!disorderRatio) {
        g_Dbs.db[i].superTbls[j].disorderRatio = 0;
      } else {
3917
        printf("ERROR: failed to read json, disorderRatio not found\n");
3918
        goto PARSE_OVER;
3919
      }
3920 3921 3922 3923 3924 3925 3926

      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 {
3927
        printf("ERROR: failed to read json, disorderRange not found\n");
3928 3929
        goto PARSE_OVER;
      }
3930

3931 3932
      cJSON* insertRows = cJSON_GetObjectItem(stbInfo, "insert_rows");
      if (insertRows && insertRows->type == cJSON_Number) {
3933 3934 3935 3936 3937
        if (insertRows->valueint < 0) {
          errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n",
                __func__, __LINE__);
          goto PARSE_OVER;
        }
3938 3939 3940 3941
        g_Dbs.db[i].superTbls[j].insertRows = insertRows->valueint;
      } else if (!insertRows) {
        g_Dbs.db[i].superTbls[j].insertRows = 0x7FFFFFFFFFFFFFFF;
      } else {
3942
        errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n",
3943
                __func__, __LINE__);
3944 3945 3946 3947 3948 3949
        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;
3950 3951 3952 3953 3954
        if (insertInterval->valueint < 0) {
          errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
                __func__, __LINE__);
          goto PARSE_OVER;
        }
3955
      } else if (!insertInterval) {
3956
        verbosePrint("%s() LN%d: stable insert interval be overrided by global %"PRIu64".\n",
3957
                __func__, __LINE__, g_args.insert_interval);
3958 3959
        g_Dbs.db[i].superTbls[j].insertInterval = g_args.insert_interval;
      } else {
3960
        errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
3961
                __func__, __LINE__);
3962 3963 3964
        goto PARSE_OVER;
      }

3965
      int retVal = getColumnAndTagTypeFromInsertJsonFile(
3966
              stbInfo, &g_Dbs.db[i].superTbls[j]);
3967 3968
      if (false == retVal) {
        goto PARSE_OVER;
3969 3970
      }
    }
3971 3972 3973 3974
  }

  ret = true;

3975
PARSE_OVER:
3976 3977 3978 3979 3980 3981 3982 3983
  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) {
3984
    tstrncpy(g_queryInfo.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3985 3986 3987 3988
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
3989
    tstrncpy(g_queryInfo.host, host->valuestring, MAX_HOSTNAME_SIZE);
3990
  } else if (!host) {
3991
    tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
3992
  } else {
3993
    printf("ERROR: failed to read json, host not found\n");
3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005
    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) {
4006
    tstrncpy(g_queryInfo.user, user->valuestring, MAX_USERNAME_SIZE);
4007
  } else if (!user) {
4008
    tstrncpy(g_queryInfo.user, "root", MAX_USERNAME_SIZE); ;
4009 4010 4011 4012
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
4013
    tstrncpy(g_queryInfo.password, password->valuestring, MAX_PASSWORD_SIZE);
4014
  } else if (!password) {
4015
    tstrncpy(g_queryInfo.password, "taosdata", MAX_PASSWORD_SIZE);;
4016
  }
H
hzcheng 已提交
4017

4018
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
4019
  if (answerPrompt && answerPrompt->type == cJSON_String
4020
          && answerPrompt->valuestring != NULL) {
4021 4022 4023 4024
    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 已提交
4025
    } else {
4026
      g_args.answer_yes = false;
H
hzcheng 已提交
4027
    }
4028 4029 4030
  } else if (!answerPrompt) {
    g_args.answer_yes = false;
  } else {
4031
    printf("ERROR: failed to read json, confirm_parameter_prompt not found\n");
4032
    goto PARSE_OVER;
4033
  }
4034

4035 4036
  cJSON* gQueryTimes = cJSON_GetObjectItem(root, "query_times");
  if (gQueryTimes && gQueryTimes->type == cJSON_Number) {
4037 4038 4039
    if (gQueryTimes->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
        __func__, __LINE__);
4040 4041
      goto PARSE_OVER;
    }
4042 4043 4044 4045
    g_args.query_times = gQueryTimes->valueint;
  } else if (!gQueryTimes) {
    g_args.query_times = 1;
  } else {
4046
    errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4047
        __func__, __LINE__);
4048 4049 4050
    goto PARSE_OVER;
  }

4051 4052
  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (dbs && dbs->type == cJSON_String && dbs->valuestring != NULL) {
4053
    tstrncpy(g_queryInfo.dbName, dbs->valuestring, MAX_DB_NAME_SIZE);
4054
  } else if (!dbs) {
4055
    printf("ERROR: failed to read json, databases not found\n");
4056
    goto PARSE_OVER;
H
hzcheng 已提交
4057
  }
4058 4059 4060

  cJSON* queryMode = cJSON_GetObjectItem(root, "query_mode");
  if (queryMode && queryMode->type == cJSON_String && queryMode->valuestring != NULL) {
4061
    tstrncpy(g_queryInfo.queryMode, queryMode->valuestring, MAX_TB_NAME_SIZE);
4062
  } else if (!queryMode) {
4063
    tstrncpy(g_queryInfo.queryMode, "taosc", MAX_TB_NAME_SIZE);
4064
  } else {
4065
    printf("ERROR: failed to read json, query_mode not found\n");
4066
    goto PARSE_OVER;
H
hzcheng 已提交
4067
  }
4068

4069
  // specified_table_query
4070 4071
  cJSON *specifiedQuery = cJSON_GetObjectItem(root, "specified_table_query");
  if (!specifiedQuery) {
4072
    g_queryInfo.specifiedQueryInfo.concurrent = 1;
4073 4074
    g_queryInfo.specifiedQueryInfo.sqlCount = 0;
  } else if (specifiedQuery->type != cJSON_Object) {
4075
    printf("ERROR: failed to read json, super_table_query not found\n");
4076
    goto PARSE_OVER;
4077
  } else {
4078 4079 4080 4081 4082
    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;
4083 4084
    }

4085
    cJSON* specifiedQueryTimes = cJSON_GetObjectItem(specifiedQuery,
4086
        "query_times");
4087
    if (specifiedQueryTimes && specifiedQueryTimes->type == cJSON_Number) {
4088 4089 4090
      if (specifiedQueryTimes->valueint < 0) {
        errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
          __func__, __LINE__);
4091 4092 4093
        goto PARSE_OVER;

      }
4094 4095 4096 4097
      g_queryInfo.specifiedQueryInfo.queryTimes = specifiedQueryTimes->valueint;
    } else if (!specifiedQueryTimes) {
      g_queryInfo.specifiedQueryInfo.queryTimes = g_args.query_times;
    } else {
4098
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4099
          __func__, __LINE__);
4100
      goto PARSE_OVER;
4101
    }
4102

4103
    cJSON* concurrent = cJSON_GetObjectItem(specifiedQuery, "concurrent");
4104
    if (concurrent && concurrent->type == cJSON_Number) {
4105 4106 4107 4108
      if (concurrent->valueint <= 0) {
        errorPrint("%s() LN%d, query sqlCount %"PRIu64" or concurrent %"PRIu64" is not correct.\n",
              __func__, __LINE__,
              g_queryInfo.specifiedQueryInfo.sqlCount,
4109
              g_queryInfo.specifiedQueryInfo.concurrent);
4110 4111
        goto PARSE_OVER;
      }
4112
      g_queryInfo.specifiedQueryInfo.concurrent = concurrent->valueint;
4113
    } else if (!concurrent) {
4114
      g_queryInfo.specifiedQueryInfo.concurrent = 1;
4115
    }
4116

4117 4118 4119 4120 4121 4122 4123
    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;
4124
      } else {
4125
        errorPrint("%s() LN%d, failed to read json, async mode input error\n",
4126
            __func__, __LINE__);
4127 4128 4129
        goto PARSE_OVER;
      }
    } else {
4130
      g_queryInfo.specifiedQueryInfo.asyncMode = SYNC_MODE;
4131
    }
4132

4133
    cJSON* interval = cJSON_GetObjectItem(specifiedQuery, "interval");
4134
    if (interval && interval->type == cJSON_Number) {
4135
      g_queryInfo.specifiedQueryInfo.subscribeInterval = interval->valueint;
4136
    } else if (!interval) {
4137 4138
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4139
      g_queryInfo.specifiedQueryInfo.subscribeInterval = 10000;
4140
    }
4141

4142
    cJSON* restart = cJSON_GetObjectItem(specifiedQuery, "restart");
4143
    if (restart && restart->type == cJSON_String && restart->valuestring != NULL) {
4144
      if (0 == strcmp("yes", restart->valuestring)) {
4145
        g_queryInfo.specifiedQueryInfo.subscribeRestart = 1;
4146
      } else if (0 == strcmp("no", restart->valuestring)) {
4147
        g_queryInfo.specifiedQueryInfo.subscribeRestart = 0;
4148
      } else {
4149
        printf("ERROR: failed to read json, subscribe restart error\n");
4150 4151 4152
        goto PARSE_OVER;
      }
    } else {
4153
      g_queryInfo.specifiedQueryInfo.subscribeRestart = 1;
4154
    }
4155

4156
    cJSON* keepProgress = cJSON_GetObjectItem(specifiedQuery, "keepProgress");
4157
    if (keepProgress
4158 4159
            && keepProgress->type == cJSON_String
            && keepProgress->valuestring != NULL) {
4160
      if (0 == strcmp("yes", keepProgress->valuestring)) {
4161
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 1;
4162
      } else if (0 == strcmp("no", keepProgress->valuestring)) {
4163
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4164
      } else {
4165
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
4166 4167 4168
        goto PARSE_OVER;
      }
    } else {
4169
      g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4170 4171
    }

4172
    // sqls
4173
    cJSON* superSqls = cJSON_GetObjectItem(specifiedQuery, "sqls");
4174
    if (!superSqls) {
4175
      g_queryInfo.specifiedQueryInfo.sqlCount = 0;
4176
    } else if (superSqls->type != cJSON_Array) {
4177
      errorPrint("%s() LN%d, failed to read json, super sqls not found\n",
4178
          __func__, __LINE__);
4179
      goto PARSE_OVER;
4180
    } else {
4181 4182
      int superSqlSize = cJSON_GetArraySize(superSqls);
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
4183
        errorPrint("%s() LN%d, failed to read json, query sql size overflow, max is %d\n",
4184
           __func__, __LINE__, MAX_QUERY_SQL_COUNT);
4185 4186
        goto PARSE_OVER;
      }
4187

4188
      g_queryInfo.specifiedQueryInfo.sqlCount = superSqlSize;
4189 4190 4191
      for (int j = 0; j < superSqlSize; ++j) {
        cJSON* sql = cJSON_GetArrayItem(superSqls, j);
        if (sql == NULL) continue;
4192

4193 4194
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
        if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) {
4195
          printf("ERROR: failed to read json, sql not found\n");
4196 4197
          goto PARSE_OVER;
        }
4198
        tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH);
H
hzcheng 已提交
4199

4200 4201
        cJSON *result = cJSON_GetObjectItem(sql, "result");
        if (NULL != result && result->type == cJSON_String && result->valuestring != NULL) {
4202
          tstrncpy(g_queryInfo.specifiedQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN);
4203
        } else if (NULL == result) {
4204
          memset(g_queryInfo.specifiedQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
4205
        } else {
4206
          printf("ERROR: failed to read json, super query result file not found\n");
4207
          goto PARSE_OVER;
4208
        }
4209 4210 4211
      }
    }
  }
4212

4213
  // super_table_query
4214 4215
  cJSON *superQuery = cJSON_GetObjectItem(root, "super_table_query");
  if (!superQuery) {
4216
    g_queryInfo.superQueryInfo.threadCnt = 1;
4217 4218
    g_queryInfo.superQueryInfo.sqlCount = 0;
  } else if (superQuery->type != cJSON_Object) {
4219
    printf("ERROR: failed to read json, sub_table_query not found\n");
4220 4221
    ret = true;
    goto PARSE_OVER;
H
hzcheng 已提交
4222
  } else {
4223
    cJSON* subrate = cJSON_GetObjectItem(superQuery, "query_interval");
4224
    if (subrate && subrate->type == cJSON_Number) {
4225
      g_queryInfo.superQueryInfo.queryInterval = subrate->valueint;
4226
    } else if (!subrate) {
4227
      g_queryInfo.superQueryInfo.queryInterval = 0;
4228 4229 4230 4231
    }

    cJSON* superQueryTimes = cJSON_GetObjectItem(superQuery, "query_times");
    if (superQueryTimes && superQueryTimes->type == cJSON_Number) {
4232 4233 4234
      if (superQueryTimes->valueint < 0) {
        errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
          __func__, __LINE__);
4235 4236
        goto PARSE_OVER;
      }
4237 4238 4239 4240
      g_queryInfo.superQueryInfo.queryTimes = superQueryTimes->valueint;
    } else if (!superQueryTimes) {
      g_queryInfo.superQueryInfo.queryTimes = g_args.query_times;
    } else {
4241
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4242
          __func__, __LINE__);
4243
      goto PARSE_OVER;
4244
    }
4245

4246
    cJSON* threads = cJSON_GetObjectItem(superQuery, "threads");
4247
    if (threads && threads->type == cJSON_Number) {
4248 4249 4250 4251 4252 4253
      if (threads->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, threads input mistake\n",
          __func__, __LINE__);
        goto PARSE_OVER;

      }
4254
      g_queryInfo.superQueryInfo.threadCnt = threads->valueint;
4255
    } else if (!threads) {
4256
      g_queryInfo.superQueryInfo.threadCnt = 1;
4257
    }
4258

4259
    //cJSON* subTblCnt = cJSON_GetObjectItem(superQuery, "childtable_count");
4260
    //if (subTblCnt && subTblCnt->type == cJSON_Number) {
4261
    //  g_queryInfo.superQueryInfo.childTblCount = subTblCnt->valueint;
4262
    //} else if (!subTblCnt) {
4263
    //  g_queryInfo.superQueryInfo.childTblCount = 0;
4264
    //}
4265

4266
    cJSON* stblname = cJSON_GetObjectItem(superQuery, "stblname");
4267 4268 4269
    if (stblname && stblname->type == cJSON_String
        && stblname->valuestring != NULL) {
      tstrncpy(g_queryInfo.superQueryInfo.sTblName, stblname->valuestring,
4270
          MAX_TB_NAME_SIZE);
4271
    } else {
4272
      errorPrint("%s() LN%d, failed to read json, super table name input error\n",
4273
          __func__, __LINE__);
4274 4275
      goto PARSE_OVER;
    }
4276

4277 4278 4279 4280 4281 4282 4283
    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;
4284
      } else {
4285
        errorPrint("%s() LN%d, failed to read json, async mode input error\n",
4286
            __func__, __LINE__);
4287 4288 4289
        goto PARSE_OVER;
      }
    } else {
4290
      g_queryInfo.superQueryInfo.asyncMode = SYNC_MODE;
4291
    }
4292

4293 4294 4295 4296 4297 4298 4299 4300 4301
    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) {
4302 4303
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4304
      g_queryInfo.superQueryInfo.subscribeInterval = 10000;
4305
    }
4306

4307
    cJSON* subrestart = cJSON_GetObjectItem(superQuery, "restart");
4308 4309
    if (subrestart && subrestart->type == cJSON_String
        && subrestart->valuestring != NULL) {
4310
      if (0 == strcmp("yes", subrestart->valuestring)) {
4311
        g_queryInfo.superQueryInfo.subscribeRestart = 1;
4312
      } else if (0 == strcmp("no", subrestart->valuestring)) {
4313
        g_queryInfo.superQueryInfo.subscribeRestart = 0;
4314
      } else {
4315
        printf("ERROR: failed to read json, subscribe restart error\n");
4316 4317 4318
        goto PARSE_OVER;
      }
    } else {
4319
      g_queryInfo.superQueryInfo.subscribeRestart = 1;
4320
    }
4321

4322
    cJSON* subkeepProgress = cJSON_GetObjectItem(superQuery, "keepProgress");
4323
    if (subkeepProgress &&
4324 4325
            subkeepProgress->type == cJSON_String
            && subkeepProgress->valuestring != NULL) {
4326
      if (0 == strcmp("yes", subkeepProgress->valuestring)) {
4327
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 1;
4328
      } else if (0 == strcmp("no", subkeepProgress->valuestring)) {
4329
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4330
      } else {
4331
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
4332 4333 4334
        goto PARSE_OVER;
      }
    } else {
4335
      g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4336
    }
4337

4338
    // sqls
4339
    cJSON* subsqls = cJSON_GetObjectItem(superQuery, "sqls");
4340
    if (!subsqls) {
4341
      g_queryInfo.superQueryInfo.sqlCount = 0;
4342
    } else if (subsqls->type != cJSON_Array) {
4343
      errorPrint("%s() LN%d: failed to read json, super sqls not found\n",
4344
          __func__, __LINE__);
4345
      goto PARSE_OVER;
4346
    } else {
4347 4348
      int superSqlSize = cJSON_GetArraySize(subsqls);
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
4349
        errorPrint("%s() LN%d, failed to read json, query sql size overflow, max is %d\n",
4350
           __func__, __LINE__, MAX_QUERY_SQL_COUNT);
4351 4352
        goto PARSE_OVER;
      }
4353

4354
      g_queryInfo.superQueryInfo.sqlCount = superSqlSize;
4355
      for (int j = 0; j < superSqlSize; ++j) {
4356 4357
        cJSON* sql = cJSON_GetArrayItem(subsqls, j);
        if (sql == NULL) continue;
4358

4359
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
4360 4361 4362
        if (!sqlStr || sqlStr->type != cJSON_String
            || sqlStr->valuestring == NULL) {
          errorPrint("%s() LN%d, failed to read json, sql not found\n",
4363
              __func__, __LINE__);
4364 4365
          goto PARSE_OVER;
        }
4366
        tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring,
4367
            MAX_QUERY_SQL_LENGTH);
4368 4369

        cJSON *result = cJSON_GetObjectItem(sql, "result");
4370 4371 4372
        if (result != NULL && result->type == cJSON_String
            && result->valuestring != NULL){
          tstrncpy(g_queryInfo.superQueryInfo.result[j],
4373
              result->valuestring, MAX_FILE_NAME_LEN);
4374
        } else if (NULL == result) {
4375
          memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
4376
        }  else {
4377
          errorPrint("%s() LN%d, failed to read json, sub query result file not found\n",
4378
              __func__, __LINE__);
4379
          goto PARSE_OVER;
4380
        }
4381 4382
      }
    }
H
hzcheng 已提交
4383 4384
  }

4385
  ret = true;
H
hzcheng 已提交
4386

4387
PARSE_OVER:
4388 4389
  return ret;
}
H
hzcheng 已提交
4390

4391
static bool getInfoFromJsonFile(char* file) {
4392
    debugPrint("%s %d %s\n", __func__, __LINE__, file);
4393

4394 4395 4396 4397 4398
  FILE *fp = fopen(file, "r");
  if (!fp) {
    printf("failed to read %s, reason:%s\n", file, strerror(errno));
    return false;
  }
H
Hui Li 已提交
4399

4400
  bool  ret = false;
4401
  int   maxLen = 6400000;
4402 4403 4404 4405 4406 4407 4408
  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 已提交
4409
  }
H
Hui Li 已提交
4410

4411 4412 4413
  content[len] = 0;
  cJSON* root = cJSON_Parse(content);
  if (root == NULL) {
4414
    printf("ERROR: failed to cjson parse %s, invalid json format\n", file);
4415 4416
    goto PARSE_OVER;
  }
H
Hui Li 已提交
4417

4418 4419 4420
  cJSON* filetype = cJSON_GetObjectItem(root, "filetype");
  if (filetype && filetype->type == cJSON_String && filetype->valuestring != NULL) {
    if (0 == strcasecmp("insert", filetype->valuestring)) {
4421
      g_args.test_mode = INSERT_TEST;
4422
    } else if (0 == strcasecmp("query", filetype->valuestring)) {
4423
      g_args.test_mode = QUERY_TEST;
4424
    } else if (0 == strcasecmp("subscribe", filetype->valuestring)) {
4425
      g_args.test_mode = SUBSCRIBE_TEST;
4426
    } else {
4427
      printf("ERROR: failed to read json, filetype not support\n");
4428 4429 4430
      goto PARSE_OVER;
    }
  } else if (!filetype) {
4431
    g_args.test_mode = INSERT_TEST;
4432
  } else {
4433
    printf("ERROR: failed to read json, filetype not found\n");
4434 4435
    goto PARSE_OVER;
  }
H
hzcheng 已提交
4436

4437
  if (INSERT_TEST == g_args.test_mode) {
4438
    ret = getMetaFromInsertJsonFile(root);
4439
  } else if ((QUERY_TEST == g_args.test_mode)
4440
          || (SUBSCRIBE_TEST == g_args.test_mode)) {
4441 4442
    ret = getMetaFromQueryJsonFile(root);
  } else {
4443
    errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n",
4444
            __func__, __LINE__);
4445
    goto PARSE_OVER;
4446
  }
4447

4448
PARSE_OVER:
4449 4450
  free(content);
  cJSON_Delete(root);
H
hzcheng 已提交
4451
  fclose(fp);
4452 4453
  return ret;
}
H
hzcheng 已提交
4454

4455
static void prepareSampleData() {
4456
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4457 4458 4459
    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 已提交
4460
      }
4461 4462 4463 4464
    }
  }
}

4465
static void postFreeResource() {
4466
  tmfclose(g_fpOfInsertResult);
4467
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4468
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
4469 4470 4471
      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 已提交
4472
      }
4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484
      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 已提交
4485
    }
4486 4487
  }
}
S
Shuaiqiang Chang 已提交
4488

4489 4490 4491
static int getRowDataFromSample(
        char* dataBuf, int64_t maxLen, int64_t timestamp,
      SSuperTable* superTblInfo, int64_t* sampleUsePos) {
4492
  if ((*sampleUsePos) == MAX_SAMPLES_ONCE_FROM_FILE) {
4493
/*    int ret = readSampleFromCsvFileToMem(superTblInfo);
4494
    if (0 != ret) {
4495
      tmfree(superTblInfo->sampleDataBuf);
4496
      superTblInfo->sampleDataBuf = NULL;
4497 4498
      return -1;
    }
4499
*/
4500 4501
    *sampleUsePos = 0;
  }
S
Shuaiqiang Chang 已提交
4502

4503
  int    dataLen = 0;
4504

4505
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
4506
          "(%" PRId64 ", ", timestamp);
4507
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
4508
          "%s", superTblInfo->sampleDataBuf + superTblInfo->lenOfOneRow * (*sampleUsePos));
4509
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");
S
Shuaiqiang Chang 已提交
4510

4511
  (*sampleUsePos)++;
4512

4513 4514
  return dataLen;
}
S
Shuaiqiang Chang 已提交
4515

4516 4517
static int64_t generateRowData(char* recBuf, int64_t timestamp, SSuperTable* stbInfo) {
  int64_t   dataLen = 0;
4518
  char  *pstr = recBuf;
4519
  int64_t maxLen = MAX_DATA_SIZE;
4520

4521
  dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "(%" PRId64 ",", timestamp);
4522

4523
  for (int i = 0; i < stbInfo->columnCount; i++) {
4524 4525
    if ((0 == strncasecmp(stbInfo->columns[i].dataType, "BINARY", strlen("BINARY")))
            || (0 == strncasecmp(stbInfo->columns[i].dataType, "NCHAR", strlen("NCHAR")))) {
4526
      if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) {
4527
        errorPrint( "binary or nchar length overflow, max size:%u\n",
4528
                (uint32_t)TSDB_MAX_BINARY_LEN);
4529
        return -1;
4530
      }
4531

4532 4533
      char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1);
      if (NULL == buf) {
4534
        errorPrint( "calloc failed! size:%d\n", stbInfo->columns[i].dataLen);
4535
        return -1;
4536 4537
      }
      rand_string(buf, stbInfo->columns[i].dataLen);
4538
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "\'%s\',", buf);
4539
      tmfree(buf);
4540
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4541
                "INT", 3)) {
4542
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4543
              "%d,", rand_int());
4544
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4545
                "BIGINT", 6)) {
4546
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4547
              "%"PRId64",", rand_bigint());
4548
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4549
                "FLOAT", 5)) {
4550
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4551
              "%f,", rand_float());
4552
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4553
                "DOUBLE", 6)) {
4554
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4555
              "%f,", rand_double());
4556
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4557
                "SMALLINT", 8)) {
4558
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4559
          "%d,", rand_smallint());
4560
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4561
          "TINYINT", strlen("TINYINT"))) {
4562
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4563
          "%d,", rand_tinyint());
4564
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4565
          "BOOL", strlen("BOOL"))) {
4566
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4567
          "%d,", rand_bool());
4568
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4569
          "TIMESTAMP", strlen("TIMESTAMP"))) {
4570
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4571
          "%"PRId64",", rand_bigint());
4572
    }  else {
4573
      errorPrint( "No support data type: %s\n", stbInfo->columns[i].dataType);
4574
      return -1;
4575
    }
S
Shuaiqiang Chang 已提交
4576
  }
4577

4578
  dataLen -= 1;
4579
  dataLen += snprintf(pstr + dataLen, maxLen - dataLen, ")");
4580

4581 4582 4583
  verbosePrint("%s() LN%d, recBuf:\n\t%s\n", __func__, __LINE__, recBuf);

  return strlen(recBuf);
4584
}
S
Shuaiqiang Chang 已提交
4585

4586
static int64_t generateData(char *recBuf, char **data_type,
4587
        int num_of_cols, int64_t timestamp, int lenOfBinary) {
4588 4589
  memset(recBuf, 0, MAX_DATA_SIZE);
  char *pstr = recBuf;
4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603
  pstr += sprintf(pstr, "(%" PRId64, timestamp);
  int c = 0;

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

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

H
Haojun Liao 已提交
4604
  for (int i = 0; i < c; i++) {
4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615
    if (strcasecmp(data_type[i % c], "TINYINT") == 0) {
      pstr += sprintf(pstr, ",%d", rand_tinyint() );
    } else if (strcasecmp(data_type[i % c], "SMALLINT") == 0) {
      pstr += sprintf(pstr, ",%d", rand_smallint());
    } else if (strcasecmp(data_type[i % c], "INT") == 0) {
      pstr += sprintf(pstr, ",%d", rand_int());
    } else if (strcasecmp(data_type[i % c], "BIGINT") == 0) {
      pstr += sprintf(pstr, ",%" PRId64, rand_bigint());
    } else if (strcasecmp(data_type[i % c], "FLOAT") == 0) {
      pstr += sprintf(pstr, ",%10.4f", rand_float());
    } else if (strcasecmp(data_type[i % c], "DOUBLE") == 0) {
4616
      double t = rand_double();
4617 4618
      pstr += sprintf(pstr, ",%20.8f", t);
    } else if (strcasecmp(data_type[i % c], "BOOL") == 0) {
4619
      bool b = taosRandom() & 1;
4620 4621
      pstr += sprintf(pstr, ",%s", b ? "true" : "false");
    } else if (strcasecmp(data_type[i % c], "BINARY") == 0) {
4622 4623
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4624
      pstr += sprintf(pstr, ",\"%s\"", s);
4625
      free(s);
4626
    } else if (strcasecmp(data_type[i % c], "NCHAR") == 0) {
4627 4628
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4629
      pstr += sprintf(pstr, ",\"%s\"", s);
4630 4631 4632
      free(s);
    }

4633
    if (strlen(recBuf) > MAX_DATA_SIZE) {
4634 4635 4636 4637 4638 4639 4640
      perror("column length too long, abort");
      exit(-1);
    }
  }

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

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

4643
  return (int32_t)strlen(recBuf);
4644 4645
}

4646
static int prepareSampleDataForSTable(SSuperTable *superTblInfo) {
4647 4648
  char* sampleDataBuf = NULL;

4649
  sampleDataBuf = calloc(
4650
            superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1);
4651
  if (sampleDataBuf == NULL) {
4652
      errorPrint("%s() LN%d, Failed to calloc %"PRIu64" Bytes, reason:%s\n",
4653 4654 4655 4656
              __func__, __LINE__,
              superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE,
              strerror(errno));
      return -1;
4657
  }
4658

4659 4660 4661 4662
  superTblInfo->sampleDataBuf = sampleDataBuf;
  int ret = readSampleFromCsvFileToMem(superTblInfo);

  if (0 != ret) {
4663 4664 4665 4666 4667
      errorPrint("%s() LN%d, read sample from csv file failed.\n",
          __func__, __LINE__);
      tmfree(sampleDataBuf);
      superTblInfo->sampleDataBuf = NULL;
      return -1;
H
Hui Li 已提交
4668
  }
4669

4670 4671 4672
  return 0;
}

4673
static int64_t execInsert(threadInfo *pThreadInfo, char *buffer, uint64_t k)
4674 4675
{
  int affectedRows;
4676
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4677

4678
  verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
4679
            __func__, __LINE__, buffer);
4680
  if (superTblInfo) {
4681
    if (0 == strncasecmp(superTblInfo->insertMode, "taosc", strlen("taosc"))) {
4682
      affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4683 4684
    } else if (0 == strncasecmp(superTblInfo->insertMode, "rest", strlen("rest"))) {
      if (0 != postProceSql(g_Dbs.host, &g_Dbs.serv_addr, g_Dbs.port, buffer)) {
4685
        affectedRows = -1;
4686
        printf("========restful return fail, threadID[%d]\n",
4687
            pThreadInfo->threadID);
4688 4689 4690
      } else {
        affectedRows = k;
      }
4691 4692 4693 4694
    } else {
      errorPrint("%s() LN%d: unknown insert mode: %s\n",
        __func__, __LINE__, superTblInfo->insertMode);
      affectedRows = 0;
4695
    }
4696
  } else {
4697
    affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4698 4699 4700 4701 4702
  }

  return affectedRows;
}

4703
static void getTableName(char *pTblName, threadInfo* pThreadInfo, uint64_t tableSeq)
4704 4705
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4706
  if (superTblInfo) {
4707
    if (superTblInfo->childTblLimit > 0) {
4708 4709 4710
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
            superTblInfo->childTblName +
            (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN);
4711
    } else {
4712

4713
        verbosePrint("[%d] %s() LN%d: from=%"PRIu64" count=%"PRIu64" seq=%"PRIu64"\n",
4714 4715 4716 4717 4718
                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);
4719 4720
    }
  } else {
4721
    snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"",
4722
        g_args.tb_prefix, tableSeq);
4723 4724 4725
  }
}

4726
static int64_t generateDataTail(
4727
        SSuperTable* superTblInfo,
4728
        uint64_t batch, char* buffer, int64_t remainderBufLen, int64_t insertRows,
4729
        int64_t startFrom, int64_t startTime, int64_t *pSamplePos, int64_t *dataLen) {
4730 4731
  uint64_t len = 0;
  uint32_t ncols_per_record = 1; // count first col ts
4732

4733 4734
  char *pstr = buffer;

4735
  if (superTblInfo == NULL) {
4736
    uint32_t datatypeSeq = 0;
4737
    while(g_args.datatype[datatypeSeq]) {
4738 4739
        datatypeSeq ++;
        ncols_per_record ++;
4740
    }
4741 4742
  }

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

4745
  uint64_t k = 0;
4746
  for (k = 0; k < batch;) {
4747
    char data[MAX_DATA_SIZE];
4748 4749
    memset(data, 0, MAX_DATA_SIZE);

4750
    int64_t retLen = 0;
4751

4752 4753
    if (superTblInfo) {
      if (0 == strncasecmp(superTblInfo->dataSource,
4754 4755 4756 4757 4758 4759 4760
                    "sample", strlen("sample"))) {
          retLen = getRowDataFromSample(
                    data,
                    remainderBufLen,
                    startTime + superTblInfo->timeStampStep * k,
                    superTblInfo,
                    pSamplePos);
4761
      } else if (0 == strncasecmp(superTblInfo->dataSource,
4762
                   "rand", strlen("rand"))) {
4763

4764
        int64_t randTail = superTblInfo->timeStampStep * k;
4765 4766 4767 4768
        if (superTblInfo->disorderRatio > 0) {
          int rand_num = taosRandom() % 100;
          if(rand_num < superTblInfo->disorderRatio) {
            randTail = (randTail + (taosRandom() % superTblInfo->disorderRange + 1)) * (-1);
4769
            debugPrint("rand data generated, back %"PRId64"\n", randTail);
4770
          }
4771 4772
        }

4773
        int64_t d = startTime
4774
                + randTail;
4775
        retLen = generateRowData(
4776 4777 4778
                      data,
                      d,
                      superTblInfo);
4779
      }
4780

4781 4782 4783
      if (retLen > remainderBufLen) {
        break;
      }
4784

4785
      pstr += snprintf(pstr , retLen + 1, "%s", data);
4786 4787 4788
      k++;
      len += retLen;
      remainderBufLen -= retLen;
4789
    } else {
4790 4791
      char **data_type = g_args.datatype;
      int lenOfBinary = g_args.len_of_binary;
4792

4793 4794 4795 4796 4797 4798
      int64_t randTail = DEFAULT_TIMESTAMP_STEP * k;

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

4800 4801
          debugPrint("rand data generated, back %"PRId64"\n", randTail);
        }
4802
      } else {
4803 4804 4805 4806
        randTail = DEFAULT_TIMESTAMP_STEP * k;
      }

      retLen = generateData(data, data_type,
4807 4808 4809
                  ncols_per_record,
                  startTime + randTail,
                  lenOfBinary);
4810

4811 4812 4813
      if (len > remainderBufLen)
        break;

H
Haojun Liao 已提交
4814
      pstr += sprintf(pstr, "%s", data);
4815 4816 4817
      k++;
      len += retLen;
      remainderBufLen -= retLen;
4818 4819
    }

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

    startFrom ++;
4824

4825
    if (startFrom >= insertRows) {
4826
      break;
4827
    }
4828
  }
4829

4830 4831 4832
  *dataLen = len;
  return k;
}
4833

4834
static int generateSQLHead(char *tableName, int32_t tableSeq,
4835 4836
        threadInfo* pThreadInfo, SSuperTable* superTblInfo,
        char *buffer, int remainderBufLen)
4837 4838
{
  int len;
4839 4840 4841 4842

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

4843 4844 4845 4846
  if (superTblInfo) {
    if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) {
      char* tagsValBuf = NULL;
      if (0 == superTblInfo->tagSource) {
4847
            tagsValBuf = generateTagVaulesForStb(superTblInfo, tableSeq);
4848
      } else {
4849 4850 4851
            tagsValBuf = getTagValueFromTagSample(
                    superTblInfo,
                    tableSeq % superTblInfo->tagSampleCount);
4852 4853
      }
      if (NULL == tagsValBuf) {
4854
        errorPrint("%s() LN%d, tag buf failed to allocate  memory\n",
4855
            __func__, __LINE__);
4856 4857 4858
        return -1;
      }

4859 4860
      len = snprintf(
          headBuf,
4861 4862 4863 4864 4865 4866 4867
                  HEAD_BUFF_LEN,
                  "%s.%s using %s.%s tags %s values",
                  pThreadInfo->db_name,
                  tableName,
                  pThreadInfo->db_name,
                  superTblInfo->sTblName,
                  tagsValBuf);
4868 4869
      tmfree(tagsValBuf);
    } else if (TBL_ALREADY_EXISTS == superTblInfo->childTblExists) {
4870 4871
      len = snprintf(
          headBuf,
4872 4873 4874 4875
                  HEAD_BUFF_LEN,
                  "%s.%s values",
                  pThreadInfo->db_name,
                  tableName);
4876
    } else {
4877 4878
      len = snprintf(
          headBuf,
4879 4880 4881 4882
                  HEAD_BUFF_LEN,
                  "%s.%s values",
                  pThreadInfo->db_name,
                  tableName);
4883 4884
    }
  } else {
4885 4886 4887 4888 4889 4890
      len = snprintf(
          headBuf,
                  HEAD_BUFF_LEN,
                  "%s.%s values",
                  pThreadInfo->db_name,
                  tableName);
4891 4892
  }

4893 4894 4895 4896 4897
  if (len > remainderBufLen)
    return -1;

  tstrncpy(buffer, headBuf, len + 1);

4898 4899 4900
  return len;
}

4901
static int64_t generateInterlaceDataBuffer(
4902 4903
        char *tableName, uint64_t batchPerTbl, uint64_t i, uint64_t batchPerTblTimes,
        uint64_t tableSeq,
4904
        threadInfo *pThreadInfo, char *buffer,
4905
        uint64_t insertRows,
4906
        int64_t startTime,
4907
        uint64_t *pRemainderBufLen)
4908
{
4909
  assert(buffer);
4910 4911 4912 4913
  char *pstr = buffer;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;

  int headLen = generateSQLHead(tableName, tableSeq, pThreadInfo,
4914
            superTblInfo, pstr, *pRemainderBufLen);
4915 4916 4917 4918 4919

  if (headLen <= 0) {
    return 0;
  }
  // generate data buffer
4920
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" buffer:\n%s\n",
4921
            pThreadInfo->threadID, __func__, __LINE__, i, buffer);
4922 4923 4924 4925

  pstr += headLen;
  *pRemainderBufLen -= headLen;

4926
  int64_t dataLen = 0;
4927

4928
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" batchPerTblTimes=%"PRIu64" batchPerTbl = %"PRIu64"\n",
4929 4930
            pThreadInfo->threadID, __func__, __LINE__,
            i, batchPerTblTimes, batchPerTbl);
4931 4932 4933 4934 4935 4936

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

4940
  int64_t k = generateDataTail(
4941 4942 4943 4944
    superTblInfo,
    batchPerTbl, pstr, *pRemainderBufLen, insertRows, 0,
    startTime,
    &(pThreadInfo->samplePos), &dataLen);
4945

4946
  if (k == batchPerTbl) {
4947 4948 4949
    pstr += dataLen;
    *pRemainderBufLen -= dataLen;
  } else {
4950
    debugPrint("%s() LN%d, generated data tail: %"PRIu64", not equal batch per table: %"PRIu64"\n",
4951
            __func__, __LINE__, k, batchPerTbl);
4952 4953
    pstr -= headLen;
    pstr[0] = '\0';
4954
    k = 0;
4955 4956 4957 4958 4959
  }

  return k;
}

4960
static int64_t generateProgressiveDataBuffer(
4961
        char *tableName,
4962
        int64_t tableSeq,
4963 4964
        threadInfo *pThreadInfo, char *buffer,
        int64_t insertRows,
4965 4966
        int64_t startFrom, int64_t startTime, int64_t *pSamplePos,
        int64_t *pRemainderBufLen)
4967 4968 4969 4970 4971 4972 4973 4974
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;

  int ncols_per_record = 1; // count first col ts

  if (superTblInfo == NULL) {
    int datatypeSeq = 0;
    while(g_args.datatype[datatypeSeq]) {
4975 4976
        datatypeSeq ++;
        ncols_per_record ++;
4977 4978 4979 4980
    }
  }

  assert(buffer != NULL);
4981
  char *pstr = buffer;
4982

4983
  int64_t k = 0;
4984

4985
  memset(buffer, 0, *pRemainderBufLen);
4986

4987
  int64_t headLen = generateSQLHead(tableName, tableSeq, pThreadInfo, superTblInfo,
4988
          buffer, *pRemainderBufLen);
4989 4990 4991 4992

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

4996
  int64_t dataLen;
4997
  k = generateDataTail(superTblInfo,
4998 4999 5000
          g_args.num_of_RPR, pstr, *pRemainderBufLen, insertRows, startFrom,
          startTime,
          pSamplePos, &dataLen);
5001

5002 5003
  return k;
}
5004

5005 5006 5007 5008 5009 5010 5011 5012 5013
static void printStatPerThread(threadInfo *pThreadInfo)
{
  fprintf(stderr, "====thread[%d] completed total inserted rows: %"PRIu64 ", total affected rows: %"PRIu64". %.2f records/second====\n",
          pThreadInfo->threadID,
          pThreadInfo->totalInsertRows,
          pThreadInfo->totalAffectedRows,
          (double)(pThreadInfo->totalAffectedRows / (pThreadInfo->totalDelay/1000.0)));
}

5014
static void* syncWriteInterlace(threadInfo *pThreadInfo) {
5015
  debugPrint("[%d] %s() LN%d: ### interlace write\n",
5016 5017
         pThreadInfo->threadID, __func__, __LINE__);

5018 5019
  uint64_t insertRows;
  uint64_t interlaceRows;
5020 5021

  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5022

5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035
  if (superTblInfo) {
    insertRows = superTblInfo->insertRows;

    if ((superTblInfo->interlaceRows == 0)
        && (g_args.interlace_rows > 0)) {
      interlaceRows = g_args.interlace_rows;
    } else {
      interlaceRows = superTblInfo->interlaceRows;
    }
  } else {
    insertRows = g_args.num_of_DPT;
    interlaceRows = g_args.interlace_rows;
  }
5036

5037
  if (interlaceRows > insertRows)
H
Haojun Liao 已提交
5038
    interlaceRows = insertRows;
5039

5040 5041
  if (interlaceRows > g_args.num_of_RPR)
    interlaceRows = g_args.num_of_RPR;
5042

5043 5044 5045 5046 5047 5048 5049 5050 5051 5052
  int insertMode;

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

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

5054
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5055
  char* buffer = calloc(maxSqlLen, 1);
5056
  if (NULL == buffer) {
5057
    errorPrint( "%s() LN%d, Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5058
              __func__, __LINE__, maxSqlLen, strerror(errno));
5059 5060 5061
    return NULL;
  }

5062
  char tableName[TSDB_TABLE_NAME_LEN];
5063 5064 5065 5066

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

5067
  int64_t nTimeStampStep = superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
5068

5069
  uint64_t insert_interval =
5070
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5071 5072
  uint64_t st = 0;
  uint64_t et = UINT64_MAX;
5073

5074 5075 5076
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5077

5078
  uint64_t tableSeq = pThreadInfo->start_table_from;
5079

5080
  debugPrint("[%d] %s() LN%d: start_table_from=%"PRIu64" ntables=%"PRIu64" insertRows=%"PRIu64"\n",
5081 5082
          pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->start_table_from,
          pThreadInfo->ntables, insertRows);
5083 5084 5085

  int64_t startTime = pThreadInfo->start_time;

5086 5087
  assert(pThreadInfo->ntables > 0);

5088 5089
  uint64_t batchPerTbl = interlaceRows;
  uint64_t batchPerTblTimes;
5090

5091
  if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
5092
    batchPerTblTimes =
5093
        g_args.num_of_RPR / interlaceRows;
5094 5095 5096 5097
  } else {
    batchPerTblTimes = 1;
  }

5098
  uint64_t generatedRecPerTbl = 0;
5099
  bool flagSleep = true;
5100
  uint64_t sleepTimeTotal = 0;
5101

5102 5103 5104
  char *strInsertInto = "insert into ";
  int nInsertBufLen = strlen(strInsertInto);

5105
  while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) {
5106
    if ((flagSleep) && (insert_interval)) {
5107 5108
        st = taosGetTimestampMs();
        flagSleep = false;
5109 5110
    }
    // generate data
5111
    memset(buffer, 0, maxSqlLen);
5112
    uint64_t remainderBufLen = maxSqlLen;
5113

5114
    char *pstr = buffer;
5115 5116 5117 5118 5119

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

5120
    uint64_t recOfBatch = 0;
5121

5122
    for (uint64_t i = 0; i < batchPerTblTimes; i ++) {
5123
      getTableName(tableName, pThreadInfo, tableSeq);
5124 5125
      if (0 == strlen(tableName)) {
        errorPrint("[%d] %s() LN%d, getTableName return null\n",
5126
            pThreadInfo->threadID, __func__, __LINE__);
5127
        free(buffer);
5128 5129
        return NULL;
      }
5130

5131
      uint64_t oldRemainderLen = remainderBufLen;
5132
      int64_t generated = generateInterlaceDataBuffer(
5133 5134 5135 5136 5137 5138
        tableName, batchPerTbl, i, batchPerTblTimes,
        tableSeq,
        pThreadInfo, pstr,
        insertRows,
        startTime,
        &remainderBufLen);
5139

5140 5141
      debugPrint("[%d] %s() LN%d, generated records is %"PRId64"\n",
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5142
      if (generated < 0) {
5143
        errorPrint("[%d] %s() LN%d, generated records is %"PRId64"\n",
5144
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5145
        goto free_of_interlace;
5146 5147
      } else if (generated == 0) {
        break;
5148 5149
      }

5150
      tableSeq ++;
5151
      recOfBatch += batchPerTbl;
5152
      pstr += (oldRemainderLen - remainderBufLen);
5153
//      startTime += batchPerTbl * superTblInfo->timeStampStep;
5154
      pThreadInfo->totalInsertRows += batchPerTbl;
5155
      verbosePrint("[%d] %s() LN%d batchPerTbl=%"PRId64" recOfBatch=%"PRId64"\n",
5156 5157
                pThreadInfo->threadID, __func__, __LINE__,
                batchPerTbl, recOfBatch);
5158

5159
      if (insertMode == INTERLACE_INSERT_MODE) {
5160 5161 5162 5163
          if (tableSeq == pThreadInfo->start_table_from + pThreadInfo->ntables) {
            // turn to first table
            tableSeq = pThreadInfo->start_table_from;
            generatedRecPerTbl += batchPerTbl;
5164

5165 5166
            startTime = pThreadInfo->start_time
              + generatedRecPerTbl * nTimeStampStep;
5167

5168 5169 5170
            flagSleep = true;
            if (generatedRecPerTbl >= insertRows)
              break;
5171

5172 5173 5174
            int remainRows = insertRows - generatedRecPerTbl;
            if ((remainRows > 0) && (batchPerTbl > remainRows))
              batchPerTbl = remainRows;
5175

5176 5177 5178 5179
            if (pThreadInfo->ntables * batchPerTbl < g_args.num_of_RPR)
                break;
          }
      }
5180

5181
      verbosePrint("[%d] %s() LN%d generatedRecPerTbl=%"PRId64" insertRows=%"PRId64"\n",
5182 5183
                pThreadInfo->threadID, __func__, __LINE__,
                generatedRecPerTbl, insertRows);
5184 5185

      if ((g_args.num_of_RPR - recOfBatch) < batchPerTbl)
5186 5187 5188
        break;
    }

5189
    verbosePrint("[%d] %s() LN%d recOfBatch=%"PRIu64" totalInsertRows=%"PRIu64"\n",
5190 5191
              pThreadInfo->threadID, __func__, __LINE__, recOfBatch,
              pThreadInfo->totalInsertRows);
5192
    verbosePrint("[%d] %s() LN%d, buffer=%s\n",
5193
           pThreadInfo->threadID, __func__, __LINE__, buffer);
5194

5195
    startTs = taosGetTimestampMs();
5196

5197
    int64_t affectedRows = execInsert(pThreadInfo, buffer, recOfBatch);
5198

5199
    endTs = taosGetTimestampMs();
5200 5201
    uint64_t delay = endTs - startTs;
    performancePrint("%s() LN%d, insert execution time is %"PRIu64"ms\n",
5202
            __func__, __LINE__, delay);
5203 5204 5205
    verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5206 5207 5208 5209 5210 5211

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

5212 5213
    if (recOfBatch != affectedRows) {
        errorPrint("[%d] %s() LN%d execInsert insert %"PRIu64", affected rows: %"PRId64"\n%s\n",
5214 5215
                pThreadInfo->threadID, __func__, __LINE__,
                recOfBatch, affectedRows, buffer);
5216
        goto free_of_interlace;
5217
    }
5218

5219
    pThreadInfo->totalAffectedRows += affectedRows;
5220

5221 5222
    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
5223
      printf("thread[%d] has currently inserted rows: %"PRIu64 ", affected rows: %"PRIu64 "\n",
5224 5225 5226
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5227 5228
      lastPrintTime = currentPrintTime;
    }
5229

5230
    if ((insert_interval) && flagSleep) {
5231
      et = taosGetTimestampMs();
5232

5233 5234
      if (insert_interval > (et - st) ) {
        int sleepTime = insert_interval - (et -st);
5235
        performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
5236
                    __func__, __LINE__, sleepTime);
5237 5238 5239
        taosMsleep(sleepTime); // ms
        sleepTimeTotal += insert_interval;
      }
5240
    }
5241 5242
  }

5243
free_of_interlace:
5244
  tmfree(buffer);
5245
  printStatPerThread(pThreadInfo);
5246 5247 5248
  return NULL;
}

5249 5250 5251 5252 5253 5254 5255 5256
// sync insertion
/*
   1 thread: 100 tables * 2000  rows/s
   1 thread: 10  tables * 20000 rows/s
   6 thread: 300 tables * 2000  rows/s

   2 taosinsertdata , 1 thread:  10  tables * 20000 rows/s
*/
5257
static void* syncWriteProgressive(threadInfo *pThreadInfo) {
5258
  debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__);
5259

5260
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5261
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5262

5263
  char* buffer = calloc(maxSqlLen, 1);
5264
  if (NULL == buffer) {
5265
    errorPrint( "Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5266 5267
              maxSqlLen,
              strerror(errno));
5268 5269
    return NULL;
  }
5270

5271 5272 5273
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5274

5275
  int64_t timeStampStep =
5276
      superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
5277
/*  int insert_interval =
5278
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5279 5280
  uint64_t st = 0;
  uint64_t et = 0xffffffff;
5281
  */
5282

5283 5284
  pThreadInfo->totalInsertRows = 0;
  pThreadInfo->totalAffectedRows = 0;
5285

5286
  pThreadInfo->samplePos = 0;
5287

5288
  for (uint64_t tableSeq =
5289 5290
          pThreadInfo->start_table_from; tableSeq <= pThreadInfo->end_table_to;
        tableSeq ++) {
5291
    int64_t start_time = pThreadInfo->start_time;
5292

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

5296
    for (uint64_t i = 0; i < insertRows;) {
5297 5298 5299 5300 5301
        /*
      if (insert_interval) {
            st = taosGetTimestampMs();
      }
      */
5302

5303 5304
      char tableName[TSDB_TABLE_NAME_LEN];
      getTableName(tableName, pThreadInfo, tableSeq);
5305
      verbosePrint("%s() LN%d: tid=%d seq=%"PRId64" tableName=%s\n",
5306 5307
             __func__, __LINE__,
             pThreadInfo->threadID, tableSeq, tableName);
5308

5309
      int64_t remainderBufLen = maxSqlLen;
5310 5311 5312 5313 5314 5315 5316 5317
      char *pstr = buffer;
      int nInsertBufLen = strlen("insert into ");

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

      pstr += len;
      remainderBufLen -= len;

5318
      int64_t generated = generateProgressiveDataBuffer(
5319 5320 5321 5322
              tableName, tableSeq, pThreadInfo, pstr, insertRows,
            i, start_time,
            &(pThreadInfo->samplePos),
            &remainderBufLen);
5323 5324 5325
      if (generated > 0)
        i += generated;
      else
5326
        goto free_of_progressive;
5327

5328
      start_time +=  generated * timeStampStep;
5329
      pThreadInfo->totalInsertRows += generated;
5330

5331
      startTs = taosGetTimestampMs();
5332

5333
      int64_t affectedRows = execInsert(pThreadInfo, buffer, generated);
5334

5335
      endTs = taosGetTimestampMs();
5336
      uint64_t delay = endTs - startTs;
5337
      performancePrint("%s() LN%d, insert execution time is %"PRId64"ms\n",
5338
              __func__, __LINE__, delay);
5339 5340 5341
      verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5342

5343 5344 5345 5346
      if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
      if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
      pThreadInfo->cntDelay++;
      pThreadInfo->totalDelay += delay;
5347

5348 5349 5350 5351 5352
      if (affectedRows < 0) {
        errorPrint("%s() LN%d, affected rows: %"PRId64"\n",
                __func__, __LINE__, affectedRows);
        goto free_of_progressive;
      }
5353 5354 5355

      pThreadInfo->totalAffectedRows += affectedRows;

5356 5357
      int64_t  currentPrintTime = taosGetTimestampMs();
      if (currentPrintTime - lastPrintTime > 30*1000) {
5358
        printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
5359 5360 5361
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5362 5363 5364
        lastPrintTime = currentPrintTime;
      }

5365
      if (i >= insertRows)
5366
        break;
5367
/*
5368
      if (insert_interval) {
5369
        et = taosGetTimestampMs();
5370

5371 5372
        if (insert_interval > ((et - st)) ) {
            int sleep_time = insert_interval - (et -st);
5373 5374
            performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
                    __func__, __LINE__, sleep_time);
5375 5376
            taosMsleep(sleep_time); // ms
        }
5377
      }
5378
      */
5379 5380
    }   // num_of_DPT

5381 5382
    if (g_args.verbose_print) {
      if ((tableSeq == pThreadInfo->ntables - 1) && superTblInfo &&
5383 5384
        (0 == strncasecmp(
                    superTblInfo->dataSource, "sample", strlen("sample")))) {
5385
          verbosePrint("%s() LN%d samplePos=%"PRId64"\n",
5386
                  __func__, __LINE__, pThreadInfo->samplePos);
5387
      }
5388
    }
5389
  } // tableSeq
5390

5391
free_of_progressive:
5392
  tmfree(buffer);
5393
  printStatPerThread(pThreadInfo);
5394
  return NULL;
H
Hui Li 已提交
5395 5396
}

5397 5398
static void* syncWrite(void *sarg) {

5399 5400
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5401

5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413
  int interlaceRows;

  if (superTblInfo) {
    if ((superTblInfo->interlaceRows == 0)
        && (g_args.interlace_rows > 0)) {
      interlaceRows = g_args.interlace_rows;
    } else {
      interlaceRows = superTblInfo->interlaceRows;
    }
  } else {
    interlaceRows = g_args.interlace_rows;
  }
5414

5415
  if (interlaceRows > 0) {
5416
    // interlace mode
5417
    return syncWriteInterlace(pThreadInfo);
5418 5419
  } else {
    // progressive mode
5420
    return syncWriteProgressive(pThreadInfo);
5421
  }
5422

5423 5424
}

5425
static void callBack(void *param, TAOS_RES *res, int code) {
5426 5427
  threadInfo* pThreadInfo = (threadInfo*)param;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5428

5429 5430
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5431
  if (insert_interval) {
5432 5433 5434
    pThreadInfo->et = taosGetTimestampMs();
    if ((pThreadInfo->et - pThreadInfo->st) < insert_interval) {
      taosMsleep(insert_interval - (pThreadInfo->et - pThreadInfo->st)); // ms
5435
    }
H
Hui Li 已提交
5436
  }
5437

5438
  char *buffer = calloc(1, pThreadInfo->superTblInfo->maxSqlLen);
5439
  char data[MAX_DATA_SIZE];
5440
  char *pstr = buffer;
5441 5442
  pstr += sprintf(pstr, "insert into %s.%s%"PRId64" values",
          pThreadInfo->db_name, pThreadInfo->tb_prefix,
5443
          pThreadInfo->start_table_from);
5444 5445 5446 5447 5448 5449 5450
//  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);
5451 5452 5453 5454
    free(buffer);
    taos_free_result(res);
    return;
  }
5455

5456
  for (int i = 0; i < g_args.num_of_RPR; i++) {
5457
    int rand_num = taosRandom() % 100;
5458
    if (0 != pThreadInfo->superTblInfo->disorderRatio
5459
            && rand_num < pThreadInfo->superTblInfo->disorderRatio) {
5460 5461
      int64_t d = pThreadInfo->lastTs - (taosRandom() % pThreadInfo->superTblInfo->disorderRange + 1);
      generateRowData(data, d, pThreadInfo->superTblInfo);
5462
    } else {
5463
      generateRowData(data, pThreadInfo->lastTs += 1000, pThreadInfo->superTblInfo);
H
Hui Li 已提交
5464
    }
5465
    pstr += sprintf(pstr, "%s", data);
5466
    pThreadInfo->counter++;
H
Hui Li 已提交
5467

5468
    if (pThreadInfo->counter >= pThreadInfo->superTblInfo->insertRows) {
5469
      break;
H
Hui Li 已提交
5470 5471
    }
  }
5472

5473
  if (insert_interval) {
5474
    pThreadInfo->st = taosGetTimestampMs();
5475
  }
5476
  taos_query_a(pThreadInfo->taos, buffer, callBack, pThreadInfo);
5477
  free(buffer);
H
Hui Li 已提交
5478

5479
  taos_free_result(res);
H
Hui Li 已提交
5480 5481
}

5482
static void *asyncWrite(void *sarg) {
5483 5484
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5485

5486 5487 5488
  pThreadInfo->st = 0;
  pThreadInfo->et = 0;
  pThreadInfo->lastTs = pThreadInfo->start_time;
5489

5490
  int insert_interval =
5491
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5492
  if (insert_interval) {
5493
    pThreadInfo->st = taosGetTimestampMs();
H
Hui Li 已提交
5494
  }
5495
  taos_query_a(pThreadInfo->taos, "show databases", callBack, pThreadInfo);
5496

5497
  tsem_wait(&(pThreadInfo->lock_sem));
H
Hui Li 已提交
5498 5499 5500 5501

  return NULL;
}

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

5528
static void startMultiThreadInsertData(int threads, char* db_name,
5529
        char* precision,SSuperTable* superTblInfo) {
5530

5531 5532
  pthread_t *pids = malloc(threads * sizeof(pthread_t));
  assert(pids != NULL);
H
Hui Li 已提交
5533

5534 5535
  threadInfo *infos = malloc(threads * sizeof(threadInfo));
  assert(infos != NULL);
5536

5537 5538
  memset(pids, 0, threads * sizeof(pthread_t));
  memset(infos, 0, threads * sizeof(threadInfo));
5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555

  //TAOS* taos;
  //if (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5)) {
  //  taos = taos_connect(g_Dbs.host, g_Dbs.user, g_Dbs.password, db_name, g_Dbs.port);
  //  if (NULL == taos) {
  //    printf("connect to server fail, reason: %s\n", taos_errstr(NULL));
  //    exit(-1);
  //  }
  //}

  int32_t timePrec = TSDB_TIME_PRECISION_MILLI;
  if (0 != precision[0]) {
    if (0 == strncasecmp(precision, "ms", 2)) {
      timePrec = TSDB_TIME_PRECISION_MILLI;
    }  else if (0 == strncasecmp(precision, "us", 2)) {
      timePrec = TSDB_TIME_PRECISION_MICRO;
    }  else {
5556
      errorPrint("Not support precision: %s\n", precision);
5557 5558 5559 5560
      exit(-1);
    }
  }

5561
  int64_t start_time;
5562 5563
  if (superTblInfo) {
    if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
5564
        start_time = taosGetTimestamp(timePrec);
5565
    } else {
5566
      if (TSDB_CODE_SUCCESS != taosParseTime(
5567 5568 5569 5570 5571
        superTblInfo->startTimestamp,
        &start_time,
        strlen(superTblInfo->startTimestamp),
        timePrec, 0)) {
          ERROR_EXIT("failed to parse time!\n");
5572
      }
5573
    }
5574
  } else {
5575
     start_time = 1500000000000;
5576 5577
  }

5578
  int64_t start = taosGetTimestampMs();
5579

5580
  // read sample data from file first
5581
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5582
              "sample", strlen("sample")))) {
5583
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5584
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
5585
              __func__, __LINE__);
5586 5587 5588 5589
      exit(-1);
    }
  }

5590
  // read sample data from file first
5591
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5592
              "sample", strlen("sample")))) {
5593
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5594
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
5595
              __func__, __LINE__);
5596 5597 5598 5599 5600
      exit(-1);
    }
  }

  TAOS* taos = taos_connect(
5601 5602
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
5603
  if (NULL == taos) {
5604
    errorPrint("%s() LN%d, connect to server fail , reason: %s\n",
5605
                __func__, __LINE__, taos_errstr(NULL));
5606 5607 5608
    exit(-1);
  }

5609 5610
  int ntables = 0;
  int startFrom;
5611

5612
  if (superTblInfo) {
5613 5614
    int64_t limit;
    uint64_t offset;
5615

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

5621
    if (superTblInfo->childTblExists == TBL_ALREADY_EXISTS) {
5622 5623
      if ((superTblInfo->childTblLimit < 0)
          || ((superTblInfo->childTblOffset + superTblInfo->childTblLimit)
5624
            > (superTblInfo->childTblCount))) {
5625 5626 5627 5628 5629 5630
        superTblInfo->childTblLimit =
            superTblInfo->childTblCount - superTblInfo->childTblOffset;
      }

      offset = superTblInfo->childTblOffset;
      limit = superTblInfo->childTblLimit;
5631
    } else {
5632 5633
      limit = superTblInfo->childTblCount;
      offset = 0;
5634 5635
    }

5636 5637 5638
    ntables = limit;
    startFrom = offset;

5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649
    if ((superTblInfo->childTblExists != TBL_NO_EXISTS)
        && ((superTblInfo->childTblOffset + superTblInfo->childTblLimit )
            > superTblInfo->childTblCount)) {
      printf("WARNING: specified offset + limit > child table count!\n");
      if (!g_args.answer_yes) {
        printf("         Press enter key to continue or Ctrl-C to stop\n\n");
        (void)getchar();
      }
    }

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

5658
    superTblInfo->childTblName = (char*)calloc(1,
5659
        limit * TSDB_TABLE_NAME_LEN);
5660
    if (superTblInfo->childTblName == NULL) {
5661
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
5662 5663 5664 5665
      taos_close(taos);
      exit(-1);
    }

5666
    uint64_t childTblCount;
5667 5668 5669 5670 5671 5672
    getChildNameOfSuperTableWithLimitAndOffset(
        taos,
        db_name, superTblInfo->sTblName,
        &superTblInfo->childTblName, &childTblCount,
        limit,
        offset);
5673 5674 5675
  } else {
    ntables = g_args.num_of_tables;
    startFrom = 0;
5676
  }
5677

5678 5679
  taos_close(taos);

5680
  uint64_t a = ntables / threads;
5681 5682 5683 5684 5685
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

5686
  uint64_t b = 0;
5687 5688 5689 5690
  if (threads != 0) {
    b = ntables % threads;
  }

5691 5692 5693 5694 5695 5696
  if ((superTblInfo)
      && (0 == strncasecmp(superTblInfo->insertMode, "rest", strlen("rest")))) {
    if (convertHostToServAddr(g_Dbs.host, g_Dbs.port, &(g_Dbs.serv_addr)) != 0)
      exit(-1);
  }

H
Hui Li 已提交
5697
  for (int i = 0; i < threads; i++) {
5698
    threadInfo *t_info = infos + i;
H
Hui Li 已提交
5699 5700
    t_info->threadID = i;
    tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE);
5701
    t_info->time_precision = timePrec;
5702 5703 5704
    t_info->superTblInfo = superTblInfo;

    t_info->start_time = start_time;
5705
    t_info->minDelay = UINT64_MAX;
5706

5707
    if ((NULL == superTblInfo) ||
5708
            (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5))) {
5709
      //t_info->taos = taos;
5710
      t_info->taos = taos_connect(
5711 5712
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
5713
      if (NULL == t_info->taos) {
5714
        errorPrint(
5715 5716
                "connect to server fail from insert sub thread, reason: %s\n",
                taos_errstr(NULL));
5717 5718 5719 5720 5721 5722
        exit(-1);
      }
    } else {
      t_info->taos = NULL;
    }

5723
/*    if ((NULL == superTblInfo)
5724
            || (0 == superTblInfo->multiThreadWriteOneTbl)) {
5725
            */
5726 5727 5728 5729
      t_info->start_table_from = startFrom;
      t_info->ntables = i<b?a+1:a;
      t_info->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
      startFrom = t_info->end_table_to + 1;
5730
/*    } else {
5731 5732
      t_info->start_table_from = 0;
      t_info->ntables = superTblInfo->childTblCount;
5733 5734
      t_info->start_time = t_info->start_time + rand_int() % 10000 - rand_tinyint();
    }
5735
*/
5736
    tsem_init(&(t_info->lock_sem), 0, 0);
5737
    if (ASYNC_MODE == g_Dbs.asyncMode) {
5738
      pthread_create(pids + i, NULL, asyncWrite, t_info);
5739 5740
    } else {
      pthread_create(pids + i, NULL, syncWrite, t_info);
5741
    }
H
Hui Li 已提交
5742
  }
5743

H
Hui Li 已提交
5744 5745 5746 5747
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

5748 5749 5750 5751
  uint64_t totalDelay = 0;
  uint64_t maxDelay = 0;
  uint64_t minDelay = UINT64_MAX;
  uint64_t cntDelay = 1;
5752 5753
  double  avgDelay = 0;

H
Hui Li 已提交
5754
  for (int i = 0; i < threads; i++) {
5755 5756
    threadInfo *t_info = infos + i;

S
TD-1057  
Shengliang Guan 已提交
5757
    tsem_destroy(&(t_info->lock_sem));
5758 5759
    taos_close(t_info->taos);

5760
    debugPrint("%s() LN%d, [%d] totalInsert=%"PRIu64" totalAffected=%"PRIu64"\n",
5761 5762 5763
            __func__, __LINE__,
            t_info->threadID, t_info->totalInsertRows,
            t_info->totalAffectedRows);
5764
    if (superTblInfo) {
5765 5766
        superTblInfo->totalAffectedRows += t_info->totalAffectedRows;
        superTblInfo->totalInsertRows += t_info->totalInsertRows;
5767
    } else {
5768 5769
        g_args.totalAffectedRows += t_info->totalAffectedRows;
        g_args.totalInsertRows += t_info->totalInsertRows;
5770
    }
5771 5772 5773 5774

    totalDelay  += t_info->totalDelay;
    cntDelay   += t_info->cntDelay;
    if (t_info->maxDelay > maxDelay) maxDelay = t_info->maxDelay;
5775
    if (t_info->minDelay < minDelay) minDelay = t_info->minDelay;
H
Hui Li 已提交
5776
  }
5777
  cntDelay -= 1;
H
Hui Li 已提交
5778

5779
  if (cntDelay == 0)    cntDelay = 1;
5780 5781
  avgDelay = (double)totalDelay / cntDelay;

5782 5783
  int64_t end = taosGetTimestampMs();
  int64_t t = end - start;
5784 5785

  if (superTblInfo) {
5786
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
5787 5788 5789 5790
          t / 1000.0, superTblInfo->totalInsertRows,
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
5791 5792 5793 5794

    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",
5795 5796 5797 5798
          t / 1000.0, superTblInfo->totalInsertRows,
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
5799
    }
5800
  } else {
5801
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n",
5802 5803 5804 5805
          t / 1000.0, g_args.totalInsertRows,
          g_args.totalAffectedRows,
          threads, db_name,
          (double)g_args.totalInsertRows / (t / 1000.0));
5806 5807 5808
    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",
5809 5810 5811 5812
          t * 1000.0, g_args.totalInsertRows,
          g_args.totalAffectedRows,
          threads, db_name,
          (double)g_args.totalInsertRows / (t / 1000.0));
5813
    }
5814
  }
5815

5816
  fprintf(stderr, "insert delay, avg: %10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
5817
          avgDelay, maxDelay, minDelay);
5818 5819
  if (g_fpOfInsertResult) {
    fprintf(g_fpOfInsertResult, "insert delay, avg:%10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
5820
          avgDelay, maxDelay, minDelay);
5821
  }
5822

5823 5824
  //taos_close(taos);

H
Hui Li 已提交
5825
  free(pids);
5826
  free(infos);
H
Hui Li 已提交
5827 5828
}

5829
static void *readTable(void *sarg) {
5830
#if 1
5831
  threadInfo *rinfo = (threadInfo *)sarg;
H
hzcheng 已提交
5832 5833
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
5834
  uint64_t sTime = rinfo->start_time;
H
hzcheng 已提交
5835 5836
  char *tb_prefix = rinfo->tb_prefix;
  FILE *fp = fopen(rinfo->fp, "a");
H
Hui Li 已提交
5837
  if (NULL == fp) {
5838
    errorPrint( "fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno));
H
Hui Li 已提交
5839 5840
    return NULL;
  }
5841

5842
    int num_of_DPT;
5843
/*  if (rinfo->superTblInfo) {
5844 5845
    num_of_DPT = rinfo->superTblInfo->insertRows; //  nrecords_per_table;
  } else {
5846
  */
5847
      num_of_DPT = g_args.num_of_DPT;
5848
//  }
5849

5850
  int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
H
hzcheng 已提交
5851
  int totalData = num_of_DPT * num_of_tables;
5852
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5853 5854 5855 5856 5857 5858 5859 5860

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

5861
  for (uint64_t j = 0; j < n; j++) {
H
hzcheng 已提交
5862
    double totalT = 0;
5863 5864 5865
    uint64_t count = 0;
    for (uint64_t i = 0; i < num_of_tables; i++) {
      sprintf(command, "select %s from %s%"PRIu64" where ts>= %" PRIu64,
5866
              aggreFunc[j], tb_prefix, i, sTime);
H
hzcheng 已提交
5867

5868
      double t = taosGetTimestampMs();
S
Shuaiqiang Chang 已提交
5869 5870
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);
H
hzcheng 已提交
5871

S
Shuaiqiang Chang 已提交
5872
      if (code != 0) {
5873
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
5874
        taos_free_result(pSql);
H
hzcheng 已提交
5875
        taos_close(taos);
5876
        fclose(fp);
5877
        return NULL;
H
hzcheng 已提交
5878 5879
      }

5880
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
5881 5882 5883
        count++;
      }

5884
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
5885 5886
      totalT += t;

S
Shuaiqiang Chang 已提交
5887
      taos_free_result(pSql);
H
hzcheng 已提交
5888 5889 5890
    }

    fprintf(fp, "|%10s  |   %10d   |  %12.2f   |   %10.2f  |\n",
S
slguan 已提交
5891
            aggreFunc[j][0] == '*' ? "   *   " : aggreFunc[j], totalData,
H
hzcheng 已提交
5892
            (double)(num_of_tables * num_of_DPT) / totalT, totalT * 1000);
5893
    printf("select %10s took %.6f second(s)\n", aggreFunc[j], totalT * 1000);
H
hzcheng 已提交
5894 5895 5896
  }
  fprintf(fp, "\n");
  fclose(fp);
5897
#endif
H
hzcheng 已提交
5898 5899 5900
  return NULL;
}

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

  int num_of_DPT = rinfo->superTblInfo->insertRows;
5913
  int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
H
hzcheng 已提交
5914
  int totalData = num_of_DPT * num_of_tables;
5915
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5916 5917 5918 5919 5920 5921 5922 5923 5924

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

  for (int j = 0; j < n; j++) {
sangshuduo's avatar
sangshuduo 已提交
5925
    char condition[BUFFER_SIZE - 30] = "\0";
B
Bomin Zhang 已提交
5926
    char tempS[64] = "\0";
H
hzcheng 已提交
5927 5928 5929 5930 5931

    int m = 10 < num_of_tables ? 10 : num_of_tables;

    for (int i = 1; i <= m; i++) {
      if (i == 1) {
5932
        sprintf(tempS, "t1 = %d", i);
H
hzcheng 已提交
5933
      } else {
5934
        sprintf(tempS, " or t1 = %d ", i);
H
hzcheng 已提交
5935 5936 5937
      }
      strcat(condition, tempS);

L
liu0x54 已提交
5938
      sprintf(command, "select %s from meters where %s", aggreFunc[j], condition);
H
hzcheng 已提交
5939 5940 5941 5942

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

5943
      double t = taosGetTimestampMs();
H
hzcheng 已提交
5944

S
Shuaiqiang Chang 已提交
5945 5946 5947 5948
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);

      if (code != 0) {
5949
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
5950
        taos_free_result(pSql);
H
hzcheng 已提交
5951
        taos_close(taos);
5952
        fclose(fp);
5953
        return NULL;
H
hzcheng 已提交
5954 5955
      }
      int count = 0;
5956
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
5957 5958
        count++;
      }
5959
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
5960

5961
      fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n",
5962 5963
              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 已提交
5964

S
Shuaiqiang Chang 已提交
5965
      taos_free_result(pSql);
H
hzcheng 已提交
5966 5967 5968 5969
    }
    fprintf(fp, "\n");
  }
  fclose(fp);
5970
#endif
H
hzcheng 已提交
5971 5972 5973
  return NULL;
}

H
Hui Li 已提交
5974

5975
static int insertTestProcess() {
5976

5977 5978 5979
  setupForAnsiEscape();
  int ret = printfInsertMeta();
  resetAfterAnsiEscape();
5980

5981 5982 5983
  if (ret == -1)
    exit(EXIT_FAILURE);

5984
  debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile);
5985 5986
  g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a");
  if (NULL == g_fpOfInsertResult) {
5987
    errorPrint( "Failed to open %s for save result\n", g_Dbs.resultFile);
5988 5989
    return -1;
  }
5990

5991 5992
  if (g_fpOfInsertResult)
    printfInsertMetaToFile(g_fpOfInsertResult);
5993

5994 5995 5996 5997
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
5998

5999 6000 6001
  init_rand_data();

  // create database and super tables
6002
  if(createDatabasesAndStables() != 0) {
6003 6004
    if (g_fpOfInsertResult)
      fclose(g_fpOfInsertResult);
6005 6006
    return -1;
  }
6007 6008

  // pretreatement
6009
  prepareSampleData();
6010

6011 6012 6013 6014
  double start;
  double end;

  // create child tables
6015
  start = taosGetTimestampMs();
6016
  createChildTables();
6017
  end = taosGetTimestampMs();
6018

6019
  if (g_totalChildTables > 0) {
6020
    fprintf(stderr, "Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
6021
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6022 6023
    if (g_fpOfInsertResult) {
      fprintf(g_fpOfInsertResult,
6024
            "Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
6025
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6026
    }
6027
  }
6028

6029
  taosMsleep(1000);
6030
  // create sub threads for inserting data
6031
  //start = taosGetTimestampMs();
6032
  for (int i = 0; i < g_Dbs.dbCount; i++) {
6033 6034 6035 6036 6037 6038 6039 6040
    if (g_Dbs.use_metric) {
      if (g_Dbs.db[i].superTblCount > 0) {
        for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {

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

          if (superTblInfo && (superTblInfo->insertRows > 0)) {
            startMultiThreadInsertData(
6041 6042 6043 6044
              g_Dbs.threadCount,
              g_Dbs.db[i].dbName,
              g_Dbs.db[i].dbCfg.precision,
              superTblInfo);
6045
          }
6046
        }
6047
      }
6048
    } else {
6049
        startMultiThreadInsertData(
6050 6051 6052
          g_Dbs.threadCount,
          g_Dbs.db[i].dbName,
          g_Dbs.db[i].dbCfg.precision,
6053
          NULL);
H
Hui Li 已提交
6054
    }
6055
  }
6056
  //end = taosGetTimestampMs();
6057

6058
  //int64_t    totalInsertRows = 0;
6059
  //int64_t    totalAffectedRows = 0;
6060
  //for (int i = 0; i < g_Dbs.dbCount; i++) {
6061
  //  for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
6062
  //  totalInsertRows+= g_Dbs.db[i].superTbls[j].totalInsertRows;
6063 6064
  //  totalAffectedRows += g_Dbs.db[i].superTbls[j].totalAffectedRows;
  //}
6065
  //printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s)\n\n", end - start, totalInsertRows, totalAffectedRows, g_Dbs.threadCount);
6066
  postFreeResource();
6067

6068 6069 6070
  return 0;
}

6071 6072
static void *specifiedTableQuery(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6073

6074
  if (pThreadInfo->taos == NULL) {
6075 6076
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
6077 6078 6079 6080
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
          g_queryInfo.port);
6081 6082
    if (taos == NULL) {
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6083
            pThreadInfo->threadID, taos_errstr(NULL));
6084 6085
      return NULL;
    } else {
6086
      pThreadInfo->taos = taos;
6087 6088 6089
    }
  }

6090 6091
  char sqlStr[MAX_DB_NAME_SIZE + 5];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6092 6093
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6094 6095 6096 6097
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
    return NULL;
  }
6098

6099 6100
  uint64_t st = 0;
  uint64_t et = 0;
6101

6102
  uint64_t queryTimes = g_queryInfo.specifiedQueryInfo.queryTimes;
6103

6104 6105 6106
  uint64_t totalQueried = 0;
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
6107

6108
  while(queryTimes --) {
6109
    if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) <
6110
            (int64_t)g_queryInfo.specifiedQueryInfo.queryInterval) {
6111
      taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval - (et - st)); // ms
6112 6113
    }

6114
    st = taosGetTimestampMs();
6115

6116
    if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", strlen("taosc"))) {
6117
      int64_t t1 = taosGetTimestampMs();
6118
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6119
      if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
6120
        sprintf(tmpFile, "%s-%d",
6121 6122
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
6123
      }
6124
      selectAndGetResult(pThreadInfo->taos,
6125
          g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq], tmpFile);
6126 6127
      int64_t t2 = taosGetTimestampMs();
      printf("=[taosc] thread[%"PRId64"] complete one sql, Spent %10.3f s\n",
6128
              taosGetSelfPthreadId(), (t2 - t1)/1000.0);
6129
    } else if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
6130
      int64_t t1 = taosGetTimestampMs();
6131
      int retCode = postProceSql(g_queryInfo.host, &(g_queryInfo.serv_addr),
6132 6133
              g_queryInfo.port,
              g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq]);
6134 6135 6136 6137
      if (0 != retCode) {
        printf("====restful return fail, threadID[%d]\n", pThreadInfo->threadID);
        return NULL;
      }
6138 6139 6140
      int64_t t2 = taosGetTimestampMs();
      printf("=[restful] thread[%"PRId64"] complete one sql, Spent %10.3f s\n",
              taosGetSelfPthreadId(), (t2 - t1)/1000.0);
6141

6142 6143 6144 6145
    } else {
      errorPrint("%s() LN%d, unknown query mode: %s\n",
        __func__, __LINE__, g_queryInfo.queryMode);
      return NULL;
6146
    }
6147 6148
    totalQueried ++;
    g_queryInfo.specifiedQueryInfo.totalQueried ++;
6149

6150
    et = taosGetTimestampMs();
6151

6152 6153
    uint64_t  currentPrintTime = taosGetTimestampMs();
    uint64_t  endTs = taosGetTimestampMs();
6154
    if (currentPrintTime - lastPrintTime > 30*1000) {
6155
      debugPrint("%s() LN%d, endTs=%"PRIu64"ms, startTs=%"PRIu64"ms\n",
6156
          __func__, __LINE__, endTs, startTs);
6157
      printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.6f\n",
6158 6159
                    pThreadInfo->threadID,
                    totalQueried,
6160
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6161
      lastPrintTime = currentPrintTime;
6162
    }
H
Hui Li 已提交
6163
  }
6164 6165
  return NULL;
}
H
Hui Li 已提交
6166

6167
static void replaceChildTblName(char* inSql, char* outSql, int tblIndex) {
6168 6169
  char sourceString[32] = "xxxx";
  char subTblName[MAX_TB_NAME_SIZE*3];
6170 6171
  sprintf(subTblName, "%s.%s",
          g_queryInfo.dbName,
6172
          g_queryInfo.superQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN);
6173 6174

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

6176 6177
  char* pos = strstr(inSql, sourceString);
  if (0 == pos) {
6178
    return;
H
Hui Li 已提交
6179
  }
6180

6181
  tstrncpy(outSql, inSql, pos - inSql + 1);
6182
  //printf("1: %s\n", outSql);
6183 6184 6185 6186
  strcat(outSql, subTblName);
  //printf("2: %s\n", outSql);
  strcat(outSql, pos+strlen(sourceString));
  //printf("3: %s\n", outSql);
H
Hui Li 已提交
6187 6188
}

6189
static void *superTableQuery(void *sarg) {
6190
  char sqlstr[1024];
6191
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6192

6193
  if (pThreadInfo->taos == NULL) {
6194 6195 6196 6197 6198 6199 6200 6201
    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",
6202
            pThreadInfo->threadID, taos_errstr(NULL));
6203 6204
      return NULL;
    } else {
6205
      pThreadInfo->taos = taos;
6206 6207 6208
    }
  }

6209 6210
  uint64_t st = 0;
  uint64_t et = (int64_t)g_queryInfo.superQueryInfo.queryInterval;
6211

6212 6213 6214
  uint64_t queryTimes = g_queryInfo.superQueryInfo.queryTimes;
  uint64_t totalQueried = 0;
  uint64_t  startTs = taosGetTimestampMs();
6215

6216
  uint64_t  lastPrintTime = taosGetTimestampMs();
6217
  while(queryTimes --) {
6218 6219 6220
    if (g_queryInfo.superQueryInfo.queryInterval
            && (et - st) < (int64_t)g_queryInfo.superQueryInfo.queryInterval) {
      taosMsleep(g_queryInfo.superQueryInfo.queryInterval - (et - st)); // ms
6221
      //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6222
    }
H
Hui Li 已提交
6223

6224
    st = taosGetTimestampMs();
6225
    for (int i = pThreadInfo->start_table_from; i <= pThreadInfo->end_table_to; i++) {
6226
      for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
6227
        memset(sqlstr,0,sizeof(sqlstr));
6228
        replaceChildTblName(g_queryInfo.superQueryInfo.sql[j], sqlstr, i);
6229
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6230
        if (g_queryInfo.superQueryInfo.result[j][0] != 0) {
6231
          sprintf(tmpFile, "%s-%d",
6232
                  g_queryInfo.superQueryInfo.result[j],
6233
                  pThreadInfo->threadID);
6234
        }
6235 6236 6237 6238 6239 6240 6241 6242
        selectAndGetResult(pThreadInfo->taos, sqlstr, tmpFile);

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

        int64_t  currentPrintTime = taosGetTimestampMs();
        int64_t  endTs = taosGetTimestampMs();
        if (currentPrintTime - lastPrintTime > 30*1000) {
6243
          printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.3f\n",
6244 6245
                    pThreadInfo->threadID,
                    totalQueried,
6246
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6247
          lastPrintTime = currentPrintTime;
6248
        }
6249
      }
H
Hui Li 已提交
6250
    }
6251
    et = taosGetTimestampMs();
6252
    printf("####thread[%"PRId64"] complete all sqls to allocate all sub-tables[%"PRIu64" - %"PRIu64"] once queries duration:%.4fs\n\n",
6253
            taosGetSelfPthreadId(),
6254 6255
            pThreadInfo->start_table_from,
            pThreadInfo->end_table_to,
6256
            (double)(et - st)/1000.0);
6257
  }
6258

6259 6260 6261
  return NULL;
}

6262
static int queryTestProcess() {
6263 6264 6265 6266

  setupForAnsiEscape();
  printfQueryMeta();
  resetAfterAnsiEscape();
6267 6268 6269 6270 6271 6272

  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
6273
          g_queryInfo.port);
6274
  if (taos == NULL) {
6275 6276
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6277 6278 6279
    exit(-1);
  }

6280
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6281 6282
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6283 6284 6285
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6286
  }
6287

6288 6289 6290 6291
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
6292

6293
  printfQuerySystemInfo(taos);
6294

6295 6296 6297 6298 6299 6300
  if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
    if (convertHostToServAddr(
        g_queryInfo.host, g_queryInfo.port, &g_queryInfo.serv_addr) != 0)
      exit(-1);
  }

6301 6302 6303
  pthread_t  *pids  = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from specify table
6304 6305
  int nConcurrent = g_queryInfo.specifiedQueryInfo.concurrent;
  int nSqlCount = g_queryInfo.specifiedQueryInfo.sqlCount;
6306

6307
  uint64_t startTs = taosGetTimestampMs();
6308

6309 6310 6311 6312 6313 6314
  if ((nSqlCount > 0) && (nConcurrent > 0)) {

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

    if ((NULL == pids) || (NULL == infos)) {
6315
      taos_close(taos);
6316
      ERROR_EXIT("memory allocation failed for create threads\n");
6317
    }
6318

6319 6320 6321 6322 6323
    for (int i = 0; i < nConcurrent; i++) {
      for (int j = 0; j < nSqlCount; j++) {
        threadInfo *t_info = infos + i * nSqlCount + j;
        t_info->threadID = i * nSqlCount + j;
        t_info->querySeq = j;
6324

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

6327 6328 6329 6330
          char sqlStr[MAX_TB_NAME_SIZE*2];
          sprintf(sqlStr, "use %s", g_queryInfo.dbName);
          verbosePrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
          if (0 != queryDbExec(taos, sqlStr, NO_INSERT_TYPE, false)) {
6331
            taos_close(taos);
6332 6333
            free(infos);
            free(pids);
6334 6335 6336
            errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
            return -1;
6337
          }
6338
        }
6339

6340
        t_info->taos = NULL;// TODO: workaround to use separate taos connection;
6341

6342
        pthread_create(pids + i * nSqlCount + j, NULL, specifiedTableQuery,
6343 6344
            t_info);
      }
6345
    }
6346
  } else {
6347
    g_queryInfo.specifiedQueryInfo.concurrent = 0;
6348
  }
6349

6350 6351
  taos_close(taos);

6352 6353 6354
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
  //==== create sub threads for query from all sub table of the super table
6355 6356 6357 6358
  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));
6359 6360

    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6361 6362
      free(infos);
      free(pids);
6363

6364
      ERROR_EXIT("memory allocation failed for create threads\n");
6365
    }
6366

6367
    uint64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
6368
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6369

6370
    uint64_t a = ntables / threads;
6371 6372 6373 6374
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6375

6376
    uint64_t b = 0;
6377 6378 6379
    if (threads != 0) {
      b = ntables % threads;
    }
6380

6381
    uint64_t startFrom = 0;
6382
    for (int i = 0; i < threads; i++) {
6383 6384
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6385

6386 6387 6388 6389
      t_info->start_table_from = startFrom;
      t_info->ntables = i<b?a+1:a;
      t_info->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
      startFrom = t_info->end_table_to + 1;
6390
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6391
      pthread_create(pidsOfSub + i, NULL, superTableQuery, t_info);
6392 6393
    }

6394
    g_queryInfo.superQueryInfo.threadCnt = threads;
6395
  } else {
6396
    g_queryInfo.superQueryInfo.threadCnt = 0;
6397
  }
6398

6399 6400 6401 6402 6403 6404
  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);
      }
    }
6405
  }
S
Shuaiqiang Chang 已提交
6406

6407
  tmfree((char*)pids);
6408
  tmfree((char*)infos);
6409

6410
  for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6411
    pthread_join(pidsOfSub[i], NULL);
H
hzcheng 已提交
6412
  }
H
Hui Li 已提交
6413

6414
  tmfree((char*)pidsOfSub);
6415
  tmfree((char*)infosOfSub);
6416

6417
//  taos_close(taos);// TODO: workaround to use separate taos connection;
6418
  uint64_t endTs = taosGetTimestampMs();
6419

6420
  uint64_t totalQueried = g_queryInfo.specifiedQueryInfo.totalQueried +
6421 6422
    g_queryInfo.superQueryInfo.totalQueried;

6423
  fprintf(stderr, "==== completed total queries: %"PRIu64", the QPS of all threads: %10.3f====\n",
6424
          totalQueried,
6425
          (double)(totalQueried/((endTs-startTs)/1000.0)));
6426 6427 6428
  return 0;
}

6429
static void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
6430
  if (res == NULL || taos_errno(res) != 0) {
6431 6432
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
6433 6434
    return;
  }
6435

6436
  getResult(res, (char*)param);
6437
  // tao_unscribe() will free result.
H
hzcheng 已提交
6438 6439
}

6440 6441
static TAOS_SUB* subscribeImpl(
        TAOS *taos, char *sql, char* topic, char* resultFileName) {
6442
  TAOS_SUB* tsub = NULL;
H
hzcheng 已提交
6443

6444
  if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) {
6445
    tsub = taos_subscribe(taos,
6446
            g_queryInfo.specifiedQueryInfo.subscribeRestart,
6447
            topic, sql, subscribe_callback, (void*)resultFileName,
6448
            g_queryInfo.specifiedQueryInfo.subscribeInterval);
6449
  } else {
6450
    tsub = taos_subscribe(taos,
6451
            g_queryInfo.specifiedQueryInfo.subscribeRestart,
6452
            topic, sql, NULL, NULL, 0);
6453
  }
6454

6455 6456 6457
  if (tsub == NULL) {
    printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
    return NULL;
6458
  }
6459

6460 6461
  return tsub;
}
H
hzcheng 已提交
6462

6463 6464
static void *superSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6465
  char subSqlstr[1024];
6466
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
H
hzcheng 已提交
6467

6468 6469 6470
  if (g_queryInfo.superQueryInfo.sqlCount == 0)
    return NULL;

6471
  if (pThreadInfo->taos == NULL) {
6472 6473 6474 6475 6476 6477 6478 6479
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
          g_queryInfo.port);
    if (taos == NULL) {
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6480
            pThreadInfo->threadID, taos_errstr(NULL));
6481 6482
      return NULL;
    } else {
6483
      pThreadInfo->taos = taos;
6484 6485 6486
    }
  }

6487 6488
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6489 6490
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6491 6492
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
6493 6494
    return NULL;
  }
6495

6496 6497 6498
  //int64_t st = 0;
  //int64_t et = 0;
  do {
6499 6500
    //if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) < g_queryInfo.specifiedQueryInfo.queryInterval) {
    //  taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval- (et - st)); // ms
6501
    //  //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6502 6503 6504 6505
    //}

    //st = taosGetTimestampMs();
    char topic[32] = {0};
6506
    for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
6507 6508
      sprintf(topic, "taosdemo-subscribe-%d", i);
      memset(subSqlstr,0,sizeof(subSqlstr));
6509
      replaceChildTblName(g_queryInfo.superQueryInfo.sql[i], subSqlstr, i);
6510
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6511
      if (g_queryInfo.superQueryInfo.result[i][0] != 0) {
6512
        sprintf(tmpFile, "%s-%d",
6513
                g_queryInfo.superQueryInfo.result[i], pThreadInfo->threadID);
6514
      }
6515
      tsub[i] = subscribeImpl(pThreadInfo->taos, subSqlstr, topic, tmpFile);
6516
      if (NULL == tsub[i]) {
6517
        taos_close(pThreadInfo->taos);
6518 6519 6520 6521
        return NULL;
      }
    }
    //et = taosGetTimestampMs();
6522
    //printf("========thread[%"PRIu64"] complete all sqls to super table once queries duration:%.4fs\n", taosGetSelfPthreadId(), (double)(et - st)/1000.0);
6523
  } while(0);
6524 6525 6526

  // start loop to consume result
  TAOS_RES* res = NULL;
6527
  while(1) {
6528
    for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
6529
      if (ASYNC_MODE == g_queryInfo.superQueryInfo.asyncMode) {
6530 6531
        continue;
      }
6532

6533
      res = taos_consume(tsub[i]);
6534 6535
      if (res) {
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6536
        if (g_queryInfo.superQueryInfo.result[i][0] != 0) {
6537
          sprintf(tmpFile, "%s-%d",
6538
                  g_queryInfo.superQueryInfo.result[i],
6539
                  pThreadInfo->threadID);
6540 6541
        }
        getResult(res, tmpFile);
H
hzcheng 已提交
6542 6543 6544
      }
    }
  }
6545
  taos_free_result(res);
6546

6547
  for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
6548
    taos_unsubscribe(tsub[i], g_queryInfo.superQueryInfo.subscribeKeepProgress);
6549
  }
6550

6551
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
6552 6553 6554
  return NULL;
}

6555 6556
static void *specifiedSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6557
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
H
hzcheng 已提交
6558

6559 6560 6561
  if (g_queryInfo.specifiedQueryInfo.sqlCount == 0)
    return NULL;

6562
  if (pThreadInfo->taos == NULL) {
6563 6564 6565 6566 6567 6568 6569 6570
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
          g_queryInfo.port);
    if (taos == NULL) {
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6571
            pThreadInfo->threadID, taos_errstr(NULL));
6572 6573
      return NULL;
    } else {
6574
      pThreadInfo->taos = taos;
6575 6576 6577
    }
  }

6578 6579
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6580
  debugPrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
6581 6582
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6583 6584
    return NULL;
  }
6585

6586 6587 6588
  //int64_t st = 0;
  //int64_t et = 0;
  do {
6589 6590
    //if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) < g_queryInfo.specifiedQueryInfo.queryInterval) {
    //  taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval- (et - st)); // ms
6591
    //  //printf("========sleep duration:%"PRIu64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6592 6593 6594 6595
    //}

    //st = taosGetTimestampMs();
    char topic[32] = {0};
6596
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6597 6598
      sprintf(topic, "taosdemo-subscribe-%d", i);
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6599
      if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) {
6600
        sprintf(tmpFile, "%s-%d",
6601
                g_queryInfo.specifiedQueryInfo.result[i], pThreadInfo->threadID);
6602
      }
6603
      tsub[i] = subscribeImpl(pThreadInfo->taos,
6604
          g_queryInfo.specifiedQueryInfo.sql[i], topic, tmpFile);
6605
      if (NULL == tsub[i]) {
6606
        taos_close(pThreadInfo->taos);
6607 6608 6609 6610
        return NULL;
      }
    }
    //et = taosGetTimestampMs();
6611
    //printf("========thread[%"PRIu64"] complete all sqls to super table once queries duration:%.4fs\n", taosGetSelfPthreadId(), (double)(et - st)/1000.0);
6612
  } while(0);
6613 6614 6615

  // start loop to consume result
  TAOS_RES* res = NULL;
6616
  while(1) {
6617
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6618
      if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) {
6619 6620
        continue;
      }
6621

6622
      res = taos_consume(tsub[i]);
6623 6624
      if (res) {
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6625
        if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) {
6626
          sprintf(tmpFile, "%s-%d",
6627
                  g_queryInfo.specifiedQueryInfo.result[i], pThreadInfo->threadID);
6628 6629 6630 6631 6632 6633
        }
        getResult(res, tmpFile);
      }
    }
  }
  taos_free_result(res);
6634

6635
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6636 6637
    taos_unsubscribe(tsub[i],
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
6638
  }
6639

6640
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
6641 6642 6643
  return NULL;
}

6644
static int subscribeTestProcess() {
6645
  setupForAnsiEscape();
6646
  printfQueryMeta();
6647
  resetAfterAnsiEscape();
6648

6649 6650
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
6651
    (void) getchar();
Y
yihaoDeng 已提交
6652
  }
6653

6654 6655 6656 6657 6658
  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
6659
          g_queryInfo.port);
6660
  if (taos == NULL) {
6661 6662
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6663 6664 6665
    exit(-1);
  }

6666
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6667 6668
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6669 6670 6671
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6672 6673
  }

6674 6675
  taos_close(taos); // TODO: workaround to use separate taos connection;

6676 6677 6678
  pthread_t  *pids = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from super table
6679 6680
  if ((g_queryInfo.specifiedQueryInfo.sqlCount <= 0) ||
          (g_queryInfo.specifiedQueryInfo.concurrent <= 0)) {
6681 6682 6683
    errorPrint("%s() LN%d, query sqlCount %"PRIu64" or concurrent %"PRIu64" is not correct.\n",
              __func__, __LINE__,
              g_queryInfo.specifiedQueryInfo.sqlCount,
6684
              g_queryInfo.specifiedQueryInfo.concurrent);
6685 6686 6687
    exit(-1);
  }

6688 6689
  pids  = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(pthread_t));
  infos = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(threadInfo));
6690
  if ((NULL == pids) || (NULL == infos)) {
6691
      errorPrint("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__);
6692
      exit(-1);
6693
  }
6694

6695
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6696 6697
      threadInfo *t_info = infos + i;
      t_info->threadID = i;
6698
      t_info->taos = NULL;  // TODO: workaround to use separate taos connection;
6699
      pthread_create(pids + i, NULL, specifiedSubscribe, t_info);
H
hzcheng 已提交
6700
  }
6701

6702
  //==== create sub threads for query from sub table
6703 6704
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
6705 6706 6707
  if ((g_queryInfo.superQueryInfo.sqlCount > 0)
          && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
    pidsOfSub  = malloc(g_queryInfo.superQueryInfo.threadCnt *
6708
            sizeof(pthread_t));
6709
    infosOfSub = malloc(g_queryInfo.superQueryInfo.threadCnt *
6710
            sizeof(threadInfo));
6711
    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6712 6713 6714
      errorPrint("%s() LN%d, malloc failed for create threads\n",
              __func__, __LINE__);
      // taos_close(taos);
6715
      exit(-1);
S
Shuaiqiang Chang 已提交
6716
    }
6717

6718
    uint64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
6719
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6720

6721
    uint64_t a = ntables / threads;
6722 6723 6724 6725
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6726

6727
    uint64_t b = 0;
6728 6729 6730
    if (threads != 0) {
      b = ntables % threads;
    }
6731

6732
    uint64_t startFrom = 0;
6733
    for (int i = 0; i < threads; i++) {
6734 6735
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6736

6737 6738 6739 6740
      t_info->start_table_from = startFrom;
      t_info->ntables = i<b?a+1:a;
      t_info->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
      startFrom = t_info->end_table_to + 1;
6741
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6742
      pthread_create(pidsOfSub + i, NULL, superSubscribe, t_info);
H
hzcheng 已提交
6743
    }
6744

6745
    g_queryInfo.superQueryInfo.threadCnt = threads;
6746

6747
    for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6748 6749
      pthread_join(pidsOfSub[i], NULL);
    }
H
hzcheng 已提交
6750
  }
6751

6752
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6753
    pthread_join(pids[i], NULL);
6754
  }
H
hzcheng 已提交
6755

6756
  tmfree((char*)pids);
6757
  tmfree((char*)infos);
H
hzcheng 已提交
6758

6759
  tmfree((char*)pidsOfSub);
6760
  tmfree((char*)infosOfSub);
6761
//   taos_close(taos);
6762
  return 0;
H
hzcheng 已提交
6763 6764
}

6765
static void initOfInsertMeta() {
6766
  memset(&g_Dbs, 0, sizeof(SDbs));
6767

6768
  // set default values
6769
  tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6770
  g_Dbs.port = 6030;
6771 6772
  tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
6773
  g_Dbs.threadCount = 2;
6774 6775

  g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
6776 6777
}

6778
static void initOfQueryMeta() {
6779
  memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo));
6780

6781
  // set default values
6782
  tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6783
  g_queryInfo.port = 6030;
6784 6785
  tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
L
Liu Tao 已提交
6786 6787
}

6788
static void setParaFromArg(){
6789
  if (g_args.host) {
6790
    tstrncpy(g_Dbs.host, g_args.host, MAX_HOSTNAME_SIZE);
6791
  } else {
6792
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6793
  }
L
Liu Tao 已提交
6794

6795
  if (g_args.user) {
6796
    tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE);
6797
  }
6798 6799

  if (g_args.password) {
6800
    tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE);
6801 6802
  }

6803 6804
  if (g_args.port) {
    g_Dbs.port = g_args.port;
6805
  }
L
Liu Tao 已提交
6806

6807 6808 6809
  g_Dbs.threadCount = g_args.num_of_threads;
  g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;

6810 6811
  g_Dbs.dbCount = 1;
  g_Dbs.db[0].drop = 1;
6812

6813
  tstrncpy(g_Dbs.db[0].dbName, g_args.database, MAX_DB_NAME_SIZE);
6814
  g_Dbs.db[0].dbCfg.replica = g_args.replica;
6815
  tstrncpy(g_Dbs.db[0].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
L
Liu Tao 已提交
6816

6817
  tstrncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN);
6818 6819 6820 6821 6822

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

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

6824 6825
  char dataString[STRING_LEN];
  char **data_type = g_args.datatype;
6826

6827
  memset(dataString, 0, STRING_LEN);
L
Liu Tao 已提交
6828

6829 6830
  if (strcasecmp(data_type[0], "BINARY") == 0
          || strcasecmp(data_type[0], "BOOL") == 0
6831
          || strcasecmp(data_type[0], "NCHAR") == 0 ) {
6832
    g_Dbs.do_aggreFunc = false;
L
Liu Tao 已提交
6833
  }
H
hzcheng 已提交
6834

6835 6836 6837 6838 6839
  if (g_args.use_metric) {
    g_Dbs.db[0].superTblCount = 1;
    tstrncpy(g_Dbs.db[0].superTbls[0].sTblName, "meters", MAX_TB_NAME_SIZE);
    g_Dbs.db[0].superTbls[0].childTblCount = g_args.num_of_tables;
    g_Dbs.threadCount = g_args.num_of_threads;
6840
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
6841
    g_Dbs.asyncMode = g_args.async_mode;
6842

6843 6844 6845 6846
    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;
6847
    tstrncpy(g_Dbs.db[0].superTbls[0].childTblPrefix,
6848 6849 6850
            g_args.tb_prefix, MAX_TB_NAME_SIZE);
    tstrncpy(g_Dbs.db[0].superTbls[0].dataSource, "rand", MAX_TB_NAME_SIZE);
    tstrncpy(g_Dbs.db[0].superTbls[0].insertMode, "taosc", MAX_TB_NAME_SIZE);
6851
    tstrncpy(g_Dbs.db[0].superTbls[0].startTimestamp,
6852
            "2017-07-14 10:40:00.000", MAX_TB_NAME_SIZE);
6853
    g_Dbs.db[0].superTbls[0].timeStampStep = DEFAULT_TIMESTAMP_STEP;
6854

6855
    g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT;
6856
    g_Dbs.db[0].superTbls[0].maxSqlLen = g_args.max_sql_len;
6857

6858 6859 6860 6861 6862
    g_Dbs.db[0].superTbls[0].columnCount = 0;
    for (int i = 0; i < MAX_NUM_DATATYPE; i++) {
      if (data_type[i] == NULL) {
        break;
      }
6863

6864
      tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
6865
              data_type[i], MAX_TB_NAME_SIZE);
6866
      g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary;
6867 6868
      g_Dbs.db[0].superTbls[0].columnCount++;
    }
6869

6870 6871 6872 6873 6874
    if (g_Dbs.db[0].superTbls[0].columnCount > g_args.num_of_CPR) {
      g_Dbs.db[0].superTbls[0].columnCount = g_args.num_of_CPR;
    } else {
      for (int i = g_Dbs.db[0].superTbls[0].columnCount; i < g_args.num_of_CPR; i++) {
        tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType, "INT", MAX_TB_NAME_SIZE);
6875
        g_Dbs.db[0].superTbls[0].columns[i].dataLen = 0;
6876 6877 6878
        g_Dbs.db[0].superTbls[0].columnCount++;
      }
    }
6879

6880
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType, "INT", MAX_TB_NAME_SIZE);
6881
    g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0;
6882

6883
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType, "BINARY", MAX_TB_NAME_SIZE);
6884 6885
    g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary;
    g_Dbs.db[0].superTbls[0].tagCount = 2;
6886
  } else {
6887 6888
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
    g_Dbs.db[0].superTbls[0].tagCount = 0;
H
hzcheng 已提交
6889
  }
6890 6891 6892 6893 6894 6895
}

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

6897 6898 6899
  /* Compile regular expression */
  if (regcomp(&regex, reg, cflags) != 0) {
    printf("Fail to compile regex\n");
H
Hui Li 已提交
6900 6901 6902
    exit(-1);
  }

6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926
  /* 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);
}

6927
static void querySqlFile(TAOS* taos, char* sqlFile)
6928 6929 6930 6931 6932 6933
{
  FILE *fp = fopen(sqlFile, "r");
  if (fp == NULL) {
    printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno));
    return;
  }
6934

6935 6936 6937 6938 6939 6940
  int       read_len = 0;
  char *    cmd = calloc(1, MAX_SQL_SIZE);
  size_t    cmd_len = 0;
  char *    line = NULL;
  size_t    line_len = 0;

6941
  double t = taosGetTimestampMs();
6942

6943
  while((read_len = tgetline(&line, &line_len, fp)) != -1) {
6944 6945 6946 6947 6948 6949 6950 6951 6952 6953 6954 6955
    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;
6956
    }
6957 6958

    memcpy(cmd + cmd_len, line, read_len);
6959
    verbosePrint("%s() LN%d cmd: %s\n", __func__, __LINE__, cmd);
6960 6961 6962
    if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE, false)) {
        errorPrint("%s() LN%d, queryDbExec %s failed!\n",
               __func__, __LINE__, cmd);
6963 6964 6965 6966 6967
        tmfree(cmd);
        tmfree(line);
        tmfclose(fp);
        return;
    }
6968 6969
    memset(cmd, 0, MAX_SQL_SIZE);
    cmd_len = 0;
H
hzcheng 已提交
6970 6971
  }

6972
  t = taosGetTimestampMs() - t;
6973
  printf("run %s took %.6f second(s)\n\n", sqlFile, t);
6974

6975 6976 6977 6978
  tmfree(cmd);
  tmfree(line);
  tmfclose(fp);
  return;
H
hzcheng 已提交
6979 6980
}

6981
static void testMetaFile() {
6982
    if (INSERT_TEST == g_args.test_mode) {
6983 6984
      if (g_Dbs.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir);
6985

6986
      insertTestProcess();
6987

6988
    } else if (QUERY_TEST == g_args.test_mode) {
6989 6990
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
6991

6992
      queryTestProcess();
6993

6994
    } else if (SUBSCRIBE_TEST == g_args.test_mode) {
6995 6996
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
6997

6998
      subscribeTestProcess();
6999

7000 7001 7002
    }  else {
      ;
    }
7003
}
7004

7005
static void queryResult() {
7006
  // query data
7007

7008 7009 7010 7011 7012
  pthread_t read_id;
  threadInfo *rInfo = malloc(sizeof(threadInfo));
  assert(rInfo);
  rInfo->start_time = 1500000000000;  // 2017-07-14 10:40:00.000
  rInfo->start_table_from = 0;
7013

7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049
  //rInfo->do_aggreFunc = g_Dbs.do_aggreFunc;
  if (g_args.use_metric) {
    rInfo->ntables = g_Dbs.db[0].superTbls[0].childTblCount;
    rInfo->end_table_to = g_Dbs.db[0].superTbls[0].childTblCount - 1;
    rInfo->superTblInfo = &g_Dbs.db[0].superTbls[0];
    tstrncpy(rInfo->tb_prefix,
          g_Dbs.db[0].superTbls[0].childTblPrefix, MAX_TB_NAME_SIZE);
  } else {
    rInfo->ntables = g_args.num_of_tables;
    rInfo->end_table_to = g_args.num_of_tables -1;
    tstrncpy(rInfo->tb_prefix, g_args.tb_prefix, MAX_TB_NAME_SIZE);
  }

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

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

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

7052 7053
static void testCmdLine() {

7054 7055 7056 7057 7058 7059 7060 7061 7062 7063
  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);
  }

7064 7065
  g_args.test_mode = INSERT_TEST;
  insertTestProcess();
7066

7067
  if (false == g_Dbs.insert_only)
7068
    queryResult();
7069 7070
}

7071 7072 7073
int main(int argc, char *argv[]) {
  parse_args(argc, argv, &g_args);

7074
  debugPrint("meta file: %s\n", g_args.metaFile);
7075 7076 7077

  if (g_args.metaFile) {
    initOfInsertMeta();
7078
    initOfQueryMeta();
7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091

    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(
7092 7093 7094 7095
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
7096
          g_Dbs.port);
7097
      querySqlFile(qtaos, g_args.sqlFile);
7098 7099 7100 7101 7102
      taos_close(qtaos);

    } else {
      testCmdLine();
    }
H
hzcheng 已提交
7103
  }
7104 7105

  return 0;
H
hzcheng 已提交
7106
}
7107