taosdemo.c 235.6 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 73 74 75 76
enum QUERY_MODE {
  SYNC_QUERY_MODE,          // 0
  ASYNC_QUERY_MODE,         // 1
  INVALID_MODE
};

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

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

#define   MAX_DATABASE_COUNT     256
103
#define INPUT_BUF_LEN   256
104

105
#define DEFAULT_TIMESTAMP_STEP  1
106

107

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

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

enum MODE {
121
  SYNC,
122 123 124
  ASYNC,
  MODE_BUT
};
125

126 127 128 129 130 131
typedef enum enum_INSERT_MODE {
    PROGRESSIVE_INSERT_MODE,
    INTERLACE_INSERT_MODE,
    INVALID_INSERT_MODE
} INSERT_MODE;

132
typedef enum enumQUERY_TYPE {
133
  NO_INSERT_TYPE,
134
  INSERT_TYPE,
135
  QUERY_TYPE_BUT
136
} QUERY_TYPE;
137 138 139 140 141 142 143

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

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

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

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

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

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

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

262
  uint32_t     columnCount;
263
  StrColumn    columns[MAX_COLUMN_COUNT];
264
  uint32_t          tagCount;
265 266 267
  StrColumn    tags[MAX_TAG_COUNT];

  char*        childTblName;
268
  char*        colsOfCreateChildTable;
269 270
  uint64_t     lenOfOneRow;
  uint64_t     lenOfTagOfOneRow;
271 272 273 274 275

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

276
  uint32_t     tagSource;    // 0: rand, 1: tag sample
277
  char*        tagDataBuf;
278 279
  uint32_t     tagSampleCount;
  uint32_t     tagUsePos;
280

281
  // statistics
282 283
  uint64_t     totalInsertRows;
  uint64_t     totalAffectedRows;
284 285 286 287 288 289
} SSuperTable;

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

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

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

typedef struct SDbs_S {
335
  char         cfgDir[MAX_FILE_NAME_LEN+1];
336
  char         host[MAX_HOSTNAME_SIZE];
337 338
  struct sockaddr_in serv_addr;

339
  uint16_t     port;
340 341
  char         user[MAX_USERNAME_SIZE];
  char         password[MAX_PASSWORD_SIZE];
342
  char         resultFile[MAX_FILE_NAME_LEN+1];
343 344 345 346
  bool         use_metric;
  bool         insert_only;
  bool         do_aggreFunc;
  bool         queryMode;
347

348 349 350
  uint32_t     threadCount;
  uint32_t     threadCountByCreateTbl;
  uint32_t     dbCount;
351 352 353
  SDataBase    db[MAX_DB_COUNT];

  // statistics
354 355
  uint64_t     totalInsertRows;
  uint64_t     totalAffectedRows;
356

357 358
} SDbs;

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

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

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

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

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

typedef struct SThreadInfo_S {
410 411 412 413 414 415 416 417 418 419 420 421 422
  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;
423 424 425
  SSuperTable* superTblInfo;

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

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

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

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

449
#ifdef WINDOWS
450 451
#define _CRT_RAND_S

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

typedef unsigned __int32 uint32_t;

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

static HANDLE g_stdoutHandle;
static DWORD g_consoleMode;

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

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

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

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

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

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

513 514
#include <time.h>

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

520
#endif // ifdef Windows
521

522
static int createDatabasesAndStables();
523
static void createChildTables();
524
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet);
525 526 527 528 529 530 531

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

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

535
SArguments g_args = {
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 566 567 568 569 570 571
                     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 已提交
572
                     (1024*1024),         // max_sql_len
573 574 575 576 577 578 579
                     10000,           // num_of_tables
                     10000,           // num_of_DPT
                     0,               // abort
                     0,               // disorderRatio
                     1000,            // disorderRange
                     1,               // method_of_delete
                     NULL             // arg_list
580 581 582 583 584 585 586 587 588 589
};



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

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

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

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

601 602 603 604
#define errorPrint(fmt, ...) \
    do { fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); } while(0)


605
///////////////////////////////////////////////////
H
hzcheng 已提交
606

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

609 610 611 612 613 614 615 616
#ifndef TAOSDEMO_COMMIT_SHA1
#define TAOSDEMO_COMMIT_SHA1 "unknown"
#endif

#ifndef TD_VERNUMBER
#define TD_VERNUMBER    "unknown"
#endif

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

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

701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
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;
}

716
static void parse_args(int argc, char *argv[], SArguments *arguments) {
717
  char **sptr;
718 719 720 721 722

  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 已提交
723 724 725 726 727
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-c need a valid path following!\n");
        exit(EXIT_FAILURE);
      }
728
      tstrncpy(configDir, argv[++i], TSDB_FILENAME_LEN);
729

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

936
      arguments->disorderRatio = atoi(argv[++i]);
937

938
      if (arguments->disorderRatio > 50) {
939
        arguments->disorderRatio = 50;
940
      }
941

942
      if (arguments->disorderRatio < 0) {
943
        arguments->disorderRatio = 0;
944
      }
945

946
    } else if (strcmp(argv[i], "-R") == 0) {
947 948 949 950 951 952
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-R need a number following!\n");
        exit(EXIT_FAILURE);
      }
953

954
      arguments->disorderRange = atoi(argv[++i]);
955 956 957
      if (arguments->disorderRange < 0)
        arguments->disorderRange = 1000;

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

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

1026 1027 1028 1029
    }
    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);
1030
    printf("# Print verbose info:                %d\n", arguments->verbose_print);
1031 1032 1033 1034 1035 1036
    printf("###################################################################\n");
    if (!arguments->answer_yes) {
        printf("Press enter key to continue\n\n");
        (void) getchar();
    }
  }
1037
}
H
hzcheng 已提交
1038

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

1049
static void tmfree(char *buf) {
1050 1051
  if (NULL != buf) {
    free(buf);
H
Hui Li 已提交
1052
  }
1053
}
H
Hui Li 已提交
1054

1055
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet) {
1056 1057 1058
  int i;
  TAOS_RES *res = NULL;
  int32_t   code = -1;
1059

1060 1061 1062 1063
  for (i = 0; i < 5; i++) {
    if (NULL != res) {
      taos_free_result(res);
      res = NULL;
H
hzcheng 已提交
1064
    }
1065

1066 1067 1068 1069
    res = taos_query(taos, command);
    code = taos_errno(res);
    if (0 == code) {
      break;
1070
    }
H
hzcheng 已提交
1071 1072
  }

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

1083 1084 1085 1086
  if (INSERT_TYPE == type) {
    int affectedRows = taos_affected_rows(res);
    taos_free_result(res);
    return affectedRows;
H
hzcheng 已提交
1087
  }
1088

1089
  taos_free_result(res);
1090 1091
  return 0;
}
H
hzcheng 已提交
1092

1093
static void getResult(TAOS_RES *res, char* resultFileName) {
1094 1095 1096 1097 1098 1099 1100 1101 1102
  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) {
1103 1104
      errorPrint("%s() LN%d, failed to open result file: %s, result will not save to file\n",
              __func__, __LINE__, resultFileName);
1105 1106
    }
  }
1107

1108 1109
  char* databuf = (char*) calloc(1, 100*1024*1024);
  if (databuf == NULL) {
1110 1111
    errorPrint("%s() LN%d, failed to malloc, warning: save result to file slowly!\n",
            __func__, __LINE__);
1112 1113
    if (fp)
        fclose(fp);
1114 1115
    return ;
  }
H
hzcheng 已提交
1116

1117 1118
  int   totalLen = 0;
  char  temp[16000];
H
hzcheng 已提交
1119

1120
  // fetch the records row by row
1121
  while((row = taos_fetch_row(res))) {
1122 1123 1124 1125
    if (totalLen >= 100*1024*1024 - 32000) {
      if (fp) fprintf(fp, "%s", databuf);
      totalLen = 0;
      memset(databuf, 0, 100*1024*1024);
H
hzcheng 已提交
1126
    }
1127 1128 1129 1130 1131 1132
    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 已提交
1133 1134
  }

1135 1136 1137 1138
  if (fp) fprintf(fp, "%s", databuf);
  tmfclose(fp);
  free(databuf);
}
H
hzcheng 已提交
1139

1140 1141 1142
static void selectAndGetResult(TAOS *taos, char *command, char* resultFileName) {
  TAOS_RES *res = taos_query(taos, command);
  if (res == NULL || taos_errno(res) != 0) {
1143
    errorPrint("%s() LN%d, failed to execute sql:%s, reason:%s\n",
1144
       __func__, __LINE__, command, taos_errstr(res));
1145 1146
    taos_free_result(res);
    return;
H
hzcheng 已提交
1147
  }
1148

1149 1150 1151
  getResult(res, resultFileName);
  taos_free_result(res);
}
H
hzcheng 已提交
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 1185 1186 1187 1188 1189 1190 1191
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;
1192
  return randfloat[cursor];
1193 1194
}

1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211
#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

1212
static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1213

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

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

1264
static int printfInsertMeta() {
1265
    SHOW_PARSE_RESULT_START();
1266

1267 1268 1269
  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);
1270
  printf("configDir:                  \033[33m%s\033[0m\n", configDir);
1271 1272 1273
  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);
1274
  printf("top insert interval:        \033[33m%"PRIu64"\033[0m\n",
1275
          g_args.insert_interval);
1276
  printf("number of records per req:  \033[33m%"PRIu64"\033[0m\n",
1277
          g_args.num_of_RPR);
1278
  printf("max sql length:             \033[33m%"PRIu64"\033[0m\n",
1279
          g_args.max_sql_len);
1280 1281

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

1283 1284
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    printf("database[\033[33m%d\033[0m]:\n", i);
1285
    printf("  database[%d] name:      \033[33m%s\033[0m\n", i, g_Dbs.db[i].dbName);
1286
    if (0 == g_Dbs.db[i].drop) {
1287 1288 1289
      printf("  drop:                  \033[33mno\033[0m\n");
    } else {
      printf("  drop:                  \033[33myes\033[0m\n");
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 1322 1323 1324 1325 1326 1327 1328
    }

    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) {
1329
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
1330
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1331
        printf("  precision:             \033[33m%s\033[0m\n",
1332
            g_Dbs.db[i].dbCfg.precision);
1333
      } else {
1334
        printf("\033[1m\033[40;31m  precision error:       %s\033[0m\n",
1335
                g_Dbs.db[i].dbCfg.precision);
1336
        return -1;
1337 1338 1339
      }
    }

1340
    printf("  super table count:     \033[33m%"PRIu64"\033[0m\n",
1341
        g_Dbs.db[i].superTblCount);
1342 1343
    for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      printf("  super table[\033[33m%"PRIu64"\033[0m]:\n", j);
1344

1345
      printf("      stbName:           \033[33m%s\033[0m\n",
1346
          g_Dbs.db[i].superTbls[j].sTblName);
1347 1348 1349 1350 1351 1352 1353 1354

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

1356 1357 1358 1359 1360 1361 1362
      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");
      }
1363

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

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

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

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

  SHOW_PARSE_RESULT_END();
1453 1454

  return 0;
1455 1456 1457
}

static void printfInsertMetaToFile(FILE* fp) {
1458 1459

  SHOW_PARSE_RESULT_START_TO_FILE(fp);
1460

1461 1462
  fprintf(fp, "host:                       %s:%u\n", g_Dbs.host, g_Dbs.port);
  fprintf(fp, "user:                       %s\n", g_Dbs.user);
1463
  fprintf(fp, "configDir:                  %s\n", configDir);
1464 1465 1466
  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);
1467 1468
  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);
1469
  fprintf(fp, "database count:          %d\n", g_Dbs.dbCount);
1470

1471 1472
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    fprintf(fp, "database[%d]:\n", i);
1473
    fprintf(fp, "  database[%d] name:       %s\n", i, g_Dbs.db[i].dbName);
1474
    if (0 == g_Dbs.db[i].drop) {
1475
      fprintf(fp, "  drop:                  no\n");
1476
    }else {
1477
      fprintf(fp, "  drop:                  yes\n");
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 1510 1511 1512 1513 1514 1515 1516
    }

    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) {
1517
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
1518
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1519 1520 1521 1522 1523 1524
        fprintf(fp, "  precision:             %s\n", g_Dbs.db[i].dbCfg.precision);
      } else {
        fprintf(fp, "  precision error:       %s\n", g_Dbs.db[i].dbCfg.precision);
      }
    }

1525
    fprintf(fp, "  super table count:     %"PRIu64"\n", g_Dbs.db[i].superTblCount);
1526 1527
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      fprintf(fp, "  super table[%d]:\n", j);
1528 1529

      fprintf(fp, "      stbName:           %s\n",  g_Dbs.db[i].superTbls[j].sTblName);
1530 1531 1532 1533 1534 1535 1536 1537

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

1539 1540 1541 1542 1543 1544 1545
      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");
      }
1546

1547
      fprintf(fp, "      childTblCount:     %"PRIu64"\n",
1548 1549 1550 1551 1552 1553 1554
              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);
1555
      fprintf(fp, "      insertRows:        %"PRIu64"\n",
1556
              g_Dbs.db[i].superTbls[j].insertRows);
1557
      fprintf(fp, "      interlace rows:    %"PRIu64"\n",
1558
              g_Dbs.db[i].superTbls[j].interlaceRows);
1559
      if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) {
1560
        fprintf(fp, "      stable insert interval:   %"PRIu64"\n",
1561
                g_Dbs.db[i].superTbls[j].insertInterval);
1562
      }
1563
/*
1564
      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1565
        fprintf(fp, "      multiThreadWriteOneTbl:  no\n");
1566
      }else {
1567
        fprintf(fp, "      multiThreadWriteOneTbl:  yes\n");
1568
      }
1569
      */
1570
      fprintf(fp, "      interlaceRows:     %"PRIu64"\n",
1571
              g_Dbs.db[i].superTbls[j].interlaceRows);
1572
      fprintf(fp, "      disorderRange:     %d\n",  g_Dbs.db[i].superTbls[j].disorderRange);
1573
      fprintf(fp, "      disorderRatio:     %d\n",  g_Dbs.db[i].superTbls[j].disorderRatio);
1574
      fprintf(fp, "      maxSqlLen:         %"PRIu64"\n",
1575
              g_Dbs.db[i].superTbls[j].maxSqlLen);
1576

1577 1578 1579 1580
      fprintf(fp, "      timeStampStep:     %"PRId64"\n",
              g_Dbs.db[i].superTbls[j].timeStampStep);
      fprintf(fp, "      startTimestamp:    %s\n",
              g_Dbs.db[i].superTbls[j].startTimestamp);
1581
      fprintf(fp, "      sampleFormat:      %s\n",  g_Dbs.db[i].superTbls[j].sampleFormat);
1582 1583 1584
      fprintf(fp, "      sampleFile:        %s\n",  g_Dbs.db[i].superTbls[j].sampleFile);
      fprintf(fp, "      tagsFile:          %s\n",  g_Dbs.db[i].superTbls[j].tagsFile);

1585 1586 1587
      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);
1588
        if ((0 == strncasecmp(
1589 1590 1591 1592
                        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")))) {
1593 1594 1595
          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);
1596 1597 1598 1599 1600
        } else {
          fprintf(fp, "column[%d]:%s ", k, g_Dbs.db[i].superTbls[j].columns[k].dataType);
        }
      }
      fprintf(fp, "\n");
1601 1602 1603

      fprintf(fp, "      tagCount:            %d\n        ",
              g_Dbs.db[i].superTbls[j].tagCount);
1604 1605
      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);
1606
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
1607 1608 1609
                        "binary", strlen("binary")))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                        "nchar", strlen("nchar")))) {
1610 1611
          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);
1612 1613
        } else {
          fprintf(fp, "tag[%d]:%s ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType);
1614
        }
1615 1616 1617 1618 1619
      }
      fprintf(fp, "\n");
    }
    fprintf(fp, "\n");
  }
1620

1621
  SHOW_PARSE_RESULT_END_TO_FILE(fp);
1622 1623 1624
}

static void printfQueryMeta() {
1625

1626
  SHOW_PARSE_RESULT_START();
1627

1628
  printf("host:                    \033[33m%s:%u\033[0m\n",
1629
          g_queryInfo.host, g_queryInfo.port);
1630 1631 1632 1633
  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");
1634 1635 1636 1637

  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",
1638
      g_queryInfo.specifiedQueryInfo.sqlCount);
1639 1640 1641
    if (g_queryInfo.specifiedQueryInfo.sqlCount > 0) {
      printf("specified tbl query times:\n");
      printf("                \033[33m%"PRIu64"\033[0m\n",
1642
      g_queryInfo.specifiedQueryInfo.queryTimes);
1643 1644 1645 1646 1647 1648 1649 1650
      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",
        (g_queryInfo.specifiedQueryInfo.mode)?"async":"sync");
      printf("interval:       \033[33m%"PRIu64"\033[0m\n",
1651
        g_queryInfo.specifiedQueryInfo.subscribeInterval);
1652
      printf("restart:        \033[33m%d\033[0m\n",
1653
        g_queryInfo.specifiedQueryInfo.subscribeRestart);
1654
      printf("keepProgress:   \033[33m%d\033[0m\n",
1655
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
1656

1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682
      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",
        (g_queryInfo.superQueryInfo.mode)?"async":"sync");
      printf("interval:       \033[33m%"PRIu64"\033[0m\n",
1683
        g_queryInfo.superQueryInfo.subscribeInterval);
1684
      printf("restart:        \033[33m%d\033[0m\n",
1685
        g_queryInfo.superQueryInfo.subscribeRestart);
1686
      printf("keepProgress:   \033[33m%d\033[0m\n",
1687
        g_queryInfo.superQueryInfo.subscribeKeepProgress);
1688

1689 1690 1691 1692 1693 1694
      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");
    }
1695
  }
1696

1697
  SHOW_PARSE_RESULT_END();
1698 1699
}

1700
static char* formatTimestamp(char* buf, int64_t val, int precision) {
1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731
  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;
}

1732
static void xDumpFieldToFile(FILE* fp, const char* val,
1733
        TAOS_FIELD* field, int32_t length, int precision) {
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 1763 1764 1765 1766 1767 1768 1769
  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:
1770
      formatTimestamp(buf, *(int64_t*)val, precision);
1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785
      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) {
1786
    errorPrint("%s() LN%d, failed to open file: %s\n", __func__, __LINE__, fname);
1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800
    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);
1801

1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821
  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;
}

1822 1823
static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) {
  TAOS_RES * res;
1824 1825
  TAOS_ROW row = NULL;
  int count = 0;
1826 1827

  res = taos_query(taos, "show databases;");
1828
  int32_t code = taos_errno(res);
1829

1830
  if (code != 0) {
1831
    errorPrint( "failed to run <show databases>, reason: %s\n", taos_errstr(res));
1832 1833 1834 1835 1836
    return -1;
  }

  TAOS_FIELD *fields = taos_fetch_fields(res);

1837
  while((row = taos_fetch_row(res)) != NULL) {
1838
    // sys database name : 'log'
1839
    if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "log",
1840
                fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) {
1841 1842
      continue;
    }
1843 1844 1845

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

1850
    tstrncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX],
1851
            fields[TSDB_SHOW_DB_NAME_INDEX].bytes);
1852
    formatTimestamp(dbInfos[count]->create_time,
1853 1854
            *(int64_t*)row[TSDB_SHOW_DB_CREATED_TIME_INDEX],
            TSDB_TIME_PRECISION_MILLI);
1855
    dbInfos[count]->ntables = *((int32_t *)row[TSDB_SHOW_DB_NTABLES_INDEX]);
1856
    dbInfos[count]->vgroups = *((int32_t *)row[TSDB_SHOW_DB_VGROUPS_INDEX]);
1857 1858
    dbInfos[count]->replica = *((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX]);
    dbInfos[count]->quorum = *((int16_t *)row[TSDB_SHOW_DB_QUORUM_INDEX]);
1859
    dbInfos[count]->days = *((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]);
1860

1861
    tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX],
1862
            fields[TSDB_SHOW_DB_KEEP_INDEX].bytes);
1863 1864 1865 1866 1867 1868 1869
    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]));
1870
    dbInfos[count]->cachelast =
1871
      (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_CACHELAST_INDEX]));
1872

1873
    tstrncpy(dbInfos[count]->precision,
1874 1875
            (char *)row[TSDB_SHOW_DB_PRECISION_INDEX],
            fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes);
1876
    dbInfos[count]->update = *((int8_t *)row[TSDB_SHOW_DB_UPDATE_INDEX]);
1877
    tstrncpy(dbInfos[count]->status, (char *)row[TSDB_SHOW_DB_STATUS_INDEX],
1878
            fields[TSDB_SHOW_DB_STATUS_INDEX].bytes);
1879

1880 1881
    count++;
    if (count > MAX_DATABASE_COUNT) {
1882
      errorPrint("%s() LN%d, The database count overflow than %d\n",
1883
         __func__, __LINE__, MAX_DATABASE_COUNT);
1884 1885 1886 1887 1888 1889 1890
      break;
    }
  }

  return count;
}

1891
static void printfDbInfoForQueryToFile(
1892
        char* filename, SDbInfo* dbInfos, int index) {
1893

1894
  if (filename[0] == 0)
1895
      return;
1896 1897 1898

  FILE *fp = fopen(filename, "at");
  if (fp == NULL) {
1899
    errorPrint( "failed to open file: %s\n", filename);
1900
    return;
1901 1902 1903 1904 1905 1906
  }

  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);
1907
  fprintf(fp, "vgroups: %d\n", dbInfos->vgroups);
1908 1909
  fprintf(fp, "replica: %d\n", dbInfos->replica);
  fprintf(fp, "quorum: %d\n", dbInfos->quorum);
1910 1911
  fprintf(fp, "days: %d\n", dbInfos->days);
  fprintf(fp, "keep0,keep1,keep(D): %s\n", dbInfos->keeplist);
1912 1913 1914 1915 1916 1917 1918
  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);
1919 1920
  fprintf(fp, "cachelast: %d\n", dbInfos->cachelast);
  fprintf(fp, "precision: %s\n", dbInfos->precision);
1921
  fprintf(fp, "update: %d\n", dbInfos->update);
1922
  fprintf(fp, "status: %s\n", dbInfos->status);
1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936
  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);
1937
  snprintf(filename, MAX_QUERY_SQL_LENGTH, "querySystemInfo-%d-%d-%d %d:%d:%d",
1938 1939
          lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min,
          lt->tm_sec);
1940

1941 1942 1943 1944 1945 1946 1947 1948 1949
  // 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);
1950

1951 1952 1953 1954
  // show databases
  res = taos_query(taos, "show databases;");
  SDbInfo** dbInfos = (SDbInfo **)calloc(MAX_DATABASE_COUNT, sizeof(SDbInfo *));
  if (dbInfos == NULL) {
1955
    errorPrint("%s() LN%d, failed to allocate memory\n", __func__, __LINE__);
1956 1957 1958
    return;
  }
  int dbCount = getDbFromServer(taos, dbInfos);
1959
  if (dbCount <= 0) {
1960 1961
      free(dbInfos);
      return;
1962
  }
1963 1964

  for (int i = 0; i < dbCount; i++) {
1965
    // printf database info
1966
    printfDbInfoForQueryToFile(filename, dbInfos[i], i);
1967

1968 1969 1970 1971
    // show db.vgroups
    snprintf(buffer, MAX_QUERY_SQL_LENGTH, "show %s.vgroups;", dbInfos[i]->name);
    res = taos_query(taos, buffer);
    xDumpResultToFile(filename, res);
1972

1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983
    // 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);
}

1984
static int postProceSql(char *host, struct sockaddr_in *pServAddr, uint16_t port, char* sqlstr)
1985
{
1986
    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";
1987

1988
    char *url = "/rest/sql";
1989

1990 1991 1992 1993
    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;
1994

1995
    int req_buf_len = strlen(sqlstr) + REQ_EXTRA_BUF_LEN;
1996

1997 1998 1999 2000 2001
    request_buf = malloc(req_buf_len);
    if (NULL == request_buf) {
      errorPrint("%s", "ERROR, cannot allocate memory.\n");
      exit(EXIT_FAILURE);
    }
2002

2003 2004
    char userpass_buf[INPUT_BUF_LEN];
    int mod_table[] = {0, 2, 1};
2005

2006 2007 2008 2009 2010 2011 2012 2013
    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', '+', '/'};
2014

2015 2016 2017 2018
    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);
2019

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

2038
    int retConn = connect(sockfd, (struct sockaddr *)pServAddr, sizeof(struct sockaddr));
2039 2040 2041 2042 2043
    debugPrint("%s() LN%d connect() return %d\n", __func__, __LINE__, retConn);
    if (retConn < 0) {
        free(request_buf);
        ERROR_EXIT("ERROR connecting");
    }
2044

2045
    memset(base64_buf, 0, INPUT_BUF_LEN);
2046

2047 2048 2049 2050 2051 2052 2053 2054
    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;
2055

2056 2057 2058 2059 2060
      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];
    }
2061

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

2065 2066 2067
    debugPrint("%s() LN%d: auth string base64 encoded: %s\n",
            __func__, __LINE__, base64_buf);
    char *auth = base64_buf;
2068

2069 2070 2071 2072 2073 2074 2075 2076 2077
    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);
2078

2079 2080 2081
    req_str_len = strlen(request_buf);
    sent = 0;
    do {
2082
#ifdef WINDOWS
2083
        bytes = send(sockfd, request_buf + sent, req_str_len - sent, 0);
2084
#else
2085
        bytes = write(sockfd, request_buf + sent, req_str_len - sent);
2086
#endif
2087 2088 2089 2090 2091 2092
        if (bytes < 0)
            ERROR_EXIT("ERROR writing message to socket");
        if (bytes == 0)
            break;
        sent+=bytes;
    } while(sent < req_str_len);
2093

2094 2095 2096 2097
    memset(response_buf, 0, RESP_BUF_LEN);
    resp_len = sizeof(response_buf) - 1;
    received = 0;
    do {
2098
#ifdef WINDOWS
2099
        bytes = recv(sockfd, response_buf + received, resp_len - received, 0);
2100
#else
2101
        bytes = read(sockfd, response_buf + received, resp_len - received);
2102
#endif
2103 2104 2105 2106 2107 2108 2109 2110
        if (bytes < 0) {
            free(request_buf);
            ERROR_EXIT("ERROR reading response from socket");
        }
        if (bytes == 0)
            break;
        received += bytes;
    } while(received < resp_len);
2111

2112 2113 2114 2115
    if (received == resp_len) {
        free(request_buf);
        ERROR_EXIT("ERROR storing complete response from socket");
    }
H
Haojun Liao 已提交
2116

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

2120
    free(request_buf);
2121
#ifdef WINDOWS
2122
    closesocket(sockfd);
2123 2124
    WSACleanup();
#else
2125
    close(sockfd);
2126
#endif
2127

2128
    return 0;
2129 2130
}

2131
static char* getTagValueFromTagSample(SSuperTable* stbInfo, int tagUsePos) {
2132 2133
  char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
  if (NULL == dataBuf) {
2134
    errorPrint("%s() LN%d, calloc failed! size:%d\n",
2135
        __func__, __LINE__, TSDB_MAX_SQL_LEN+1);
2136 2137
    return NULL;
  }
2138

2139
  int    dataLen = 0;
2140
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2141
          "(%s)", stbInfo->tagDataBuf + stbInfo->lenOfTagOfOneRow * tagUsePos);
2142

2143 2144 2145
  return dataBuf;
}

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

2165 2166
      int tagBufLen = stbInfo->tags[i].dataLen + 1;
      char* buf = (char*)calloc(tagBufLen, 1);
2167 2168 2169 2170 2171
      if (NULL == buf) {
        printf("calloc failed! size:%d\n", stbInfo->tags[i].dataLen);
        tmfree(dataBuf);
        return NULL;
      }
2172 2173 2174 2175 2176 2177 2178

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

2221
  dataLen -= 2;
2222
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")");
2223 2224 2225
  return dataBuf;
}

2226
static int calcRowLen(SSuperTable*  superTbls) {
2227 2228
  int colIndex;
  int  lenOfOneRow = 0;
2229

2230 2231
  for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) {
    char* dataType = superTbls->columns[colIndex].dataType;
2232

2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248
    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;
2249
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2250
      lenOfOneRow += 42;
2251
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264
      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;
2265

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

  superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow;
2291

2292 2293 2294 2295
  return 0;
}


2296
static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos,
2297
        char* dbName, char* sTblName, char** childTblNameOfSuperTbl,
2298
        uint64_t* childTblCountOfSuperTbl, int64_t limit, uint64_t offset) {
2299

2300
  char command[BUFFER_SIZE] = "\0";
2301 2302
  char limitBuf[100] = "\0";

2303
  TAOS_RES * res;
2304 2305 2306
  TAOS_ROW row = NULL;

  char* childTblName = *childTblNameOfSuperTbl;
2307 2308

  if (offset >= 0) {
2309
    snprintf(limitBuf, 100, " limit %"PRId64" offset %"PRIu64"",
2310
            limit, offset);
2311 2312
  }

2313
  //get all child table name use cmd: select tbname from superTblName;
2314
  snprintf(command, BUFFER_SIZE, "select tbname from %s.%s %s",
2315
          dbName, sTblName, limitBuf);
2316

2317
  res = taos_query(taos, command);
2318 2319 2320 2321
  int32_t code = taos_errno(res);
  if (code != 0) {
    taos_free_result(res);
    taos_close(taos);
2322
    errorPrint("%s() LN%d, failed to run command %s\n",
2323
           __func__, __LINE__, command);
2324 2325 2326
    exit(-1);
  }

2327
  int childTblCount = (limit < 0)?10000:limit;
2328
  int count = 0;
2329 2330 2331
  if (childTblName == NULL) {
    childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (NULL ==  childTblName) {
2332 2333 2334 2335
    taos_free_result(res);
        taos_close(taos);
        errorPrint("%s() LN%d, failed to allocate memory!\n", __func__, __LINE__);
        exit(-1);
2336 2337 2338
    }
  }

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

2366 2367 2368 2369 2370 2371 2372
  *childTblCountOfSuperTbl = count;
  *childTblNameOfSuperTbl  = childTblName;

  taos_free_result(res);
  return 0;
}

2373
static int getAllChildNameOfSuperTable(TAOS * taos, char* dbName,
2374
        char* sTblName, char** childTblNameOfSuperTbl,
2375
        uint64_t* childTblCountOfSuperTbl) {
2376

2377 2378
    return getChildNameOfSuperTableWithLimitAndOffset(taos, dbName, sTblName,
            childTblNameOfSuperTbl, childTblCountOfSuperTbl,
2379
            -1, 0);
2380 2381
}

2382
static int getSuperTableFromServer(TAOS * taos, char* dbName,
2383
        SSuperTable*  superTbls) {
2384

2385
  char command[BUFFER_SIZE] = "\0";
2386
  TAOS_RES * res;
2387 2388
  TAOS_ROW row = NULL;
  int count = 0;
2389

2390
  //get schema use cmd: describe superTblName;
2391
  snprintf(command, BUFFER_SIZE, "describe %s.%s", dbName, superTbls->sTblName);
2392
  res = taos_query(taos, command);
2393 2394 2395
  int32_t code = taos_errno(res);
  if (code != 0) {
    printf("failed to run command %s\n", command);
2396
    taos_free_result(res);
2397 2398 2399 2400 2401 2402
    return -1;
  }

  int tagIndex = 0;
  int columnIndex = 0;
  TAOS_FIELD *fields = taos_fetch_fields(res);
2403
  while((row = taos_fetch_row(res)) != NULL) {
2404 2405 2406
    if (0 == count) {
      count++;
      continue;
2407
    }
2408 2409

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

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

  calcRowLen(superTbls);

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

H
Haojun Liao 已提交
2463
static int createSuperTable(
2464 2465
        TAOS * taos, char* dbName,
        SSuperTable*  superTbl) {
H
Haojun Liao 已提交
2466

2467
  char command[BUFFER_SIZE] = "\0";
2468

2469 2470 2471 2472 2473
  char cols[STRING_LEN] = "\0";
  int colIndex;
  int len = 0;

  int  lenOfOneRow = 0;
2474 2475 2476

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

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

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

2526 2527
  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);
2528 2529

  // save for creating child table
2530 2531 2532
  superTbl->colsOfCreateChildTable = (char*)calloc(len+20, 1);
  if (NULL == superTbl->colsOfCreateChildTable) {
    errorPrint("%s() LN%d, Failed when calloc, size:%d",
2533
           __func__, __LINE__, len+1);
2534 2535 2536 2537
    taos_close(taos);
    exit(-1);
  }

2538
  snprintf(superTbl->colsOfCreateChildTable, len+20, "(ts timestamp%s)", cols);
2539
  verbosePrint("%s() LN%d: %s\n",
2540
      __func__, __LINE__, superTbl->colsOfCreateChildTable);
2541

2542 2543
  if (superTbl->tagCount == 0) {
    errorPrint("%s() LN%d, super table tag count is %d\n",
2544
            __func__, __LINE__, superTbl->tagCount);
2545 2546
    return -1;
  }
2547

2548 2549 2550
  char tags[STRING_LEN] = "\0";
  int tagIndex;
  len = 0;
2551

2552 2553 2554 2555
  int lenOfTagOfOneRow = 0;
  len += snprintf(tags + len, STRING_LEN - len, "(");
  for (tagIndex = 0; tagIndex < superTbl->tagCount; tagIndex++) {
    char* dataType = superTbl->tags[tagIndex].dataType;
2556

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

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

  superTbl->lenOfTagOfOneRow = lenOfTagOfOneRow;

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

  if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2612 2613 2614
      errorPrint( "create supertable %s failed!\n\n",
              superTbl->sTblName);
      return -1;
2615 2616
  }
  debugPrint("create supertable %s success!\n\n", superTbl->sTblName);
2617 2618 2619
  return 0;
}

2620
static int createDatabasesAndStables() {
2621 2622 2623 2624
  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) {
2625
    errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL));
2626
    return -1;
2627 2628 2629
  }
  char command[BUFFER_SIZE] = "\0";

2630
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2631 2632
    if (g_Dbs.db[i].drop) {
      sprintf(command, "drop database if exists %s;", g_Dbs.db[i].dbName);
2633
      verbosePrint("%s() %d command: %s\n", __func__, __LINE__, command);
2634
      if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2635 2636 2637 2638
        taos_close(taos);
        return -1;
      }

2639
      int dataLen = 0;
2640
      dataLen += snprintf(command + dataLen,
2641
          BUFFER_SIZE - dataLen, "create database if not exists %s", g_Dbs.db[i].dbName);
2642

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

      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);
2713 2714
    }

2715
    debugPrint("%s() LN%d supertbl count:%"PRIu64"\n",
2716
            __func__, __LINE__, g_Dbs.db[i].superTblCount);
2717 2718 2719

    int validStbCount = 0;

2720
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
2721 2722 2723 2724 2725 2726 2727
      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)) {
2728
        ret = createSuperTable(taos, g_Dbs.db[i].dbName,
2729
                &g_Dbs.db[i].superTbls[j]);
2730

2731
        if (0 != ret) {
2732 2733
          errorPrint("create super table %d failed!\n\n", j);
          continue;
2734 2735 2736
        }
      }

2737
      ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName,
2738
                &g_Dbs.db[i].superTbls[j]);
2739 2740
      if (0 != ret) {
        errorPrint("\nget super table %s.%s info failed!\n\n",
2741
                g_Dbs.db[i].dbName, g_Dbs.db[i].superTbls[j].sTblName);
2742
        continue;
2743
      }
2744 2745

      validStbCount ++;
2746
    }
2747 2748

    g_Dbs.db[i].superTblCount = validStbCount;
2749 2750 2751 2752 2753 2754
  }

  taos_close(taos);
  return 0;
}

2755 2756
static void* createTable(void *sarg)
{
2757 2758
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
2759 2760 2761

  int64_t  lastPrintTime = taosGetTimestampMs();

2762
  int buff_len;
2763
  buff_len = BUFFER_SIZE / 8;
2764

2765
  char *buffer = calloc(buff_len, 1);
2766
  if (buffer == NULL) {
2767
    errorPrint("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__);
2768 2769
    exit(-1);
  }
2770 2771 2772

  int len = 0;
  int batchNum = 0;
2773

2774
  verbosePrint("%s() LN%d: Creating table from %"PRIu64" to %"PRIu64"\n",
2775 2776
          __func__, __LINE__,
          pThreadInfo->start_table_from, pThreadInfo->end_table_to);
2777

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

    len = 0;
2828
    verbosePrint("%s() LN%d %s\n", __func__, __LINE__, buffer);
2829
    if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)){
2830
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2831
      free(buffer);
2832 2833 2834 2835 2836
      return NULL;
    }

    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
2837
      printf("thread[%d] already create %"PRIu64" - %"PRIu64" tables\n",
2838
              pThreadInfo->threadID, pThreadInfo->start_table_from, i);
2839 2840 2841
      lastPrintTime = currentPrintTime;
    }
  }
2842

2843
  if (0 != len) {
2844
    verbosePrint("%s() %d buffer: %s\n", __func__, __LINE__, buffer);
2845
    if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)) {
2846
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2847
    }
2848
  }
2849

2850 2851 2852 2853
  free(buffer);
  return NULL;
}

2854
static int startMultiThreadCreateChildTable(
2855
        char* cols, int threads, uint64_t startFrom, uint64_t ntables,
2856
        char* db_name, SSuperTable* superTblInfo) {
2857

2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869
  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;
  }

2870
  uint64_t a = ntables / threads;
2871 2872 2873 2874 2875
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

2876
  uint64_t b = 0;
2877
  b = ntables % threads;
2878

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

    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;
2903
    t_info->use_metric = true;
2904
    t_info->cols = cols;
2905
    t_info->minDelay = UINT64_MAX;
2906 2907
    pthread_create(pids + i, NULL, createTable, t_info);
  }
2908

2909 2910 2911 2912 2913 2914 2915 2916 2917 2918
  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);
2919
  free(infos);
2920 2921

  return 0;
2922 2923
}

2924
static void createChildTables() {
2925 2926
    char tblColsBuf[MAX_SQL_SIZE];
    int len;
2927

2928
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2929 2930
    if (g_Dbs.use_metric) {
      if (g_Dbs.db[i].superTblCount > 0) {
2931
          // with super table
2932 2933
        for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
          if ((AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable)
2934
                || (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists)) {
2935 2936
            continue;
          }
2937

2938
          verbosePrint("%s() LN%d: %s\n", __func__, __LINE__,
2939
                  g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
2940 2941 2942 2943
          int startFrom = 0;
          g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount;

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

2969
      snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ")");
2970

2971
      verbosePrint("%s() LN%d: dbName: %s num of tb: %"PRIu64" schema: %s\n",
2972 2973
              __func__, __LINE__,
              g_Dbs.db[i].dbName, g_args.num_of_tables, tblColsBuf);
2974
      startMultiThreadCreateChildTable(
2975 2976 2977 2978 2979 2980
            tblColsBuf,
            g_Dbs.threadCountByCreateTbl,
            0,
            g_args.num_of_tables,
            g_Dbs.db[i].dbName,
            NULL);
2981
    }
2982 2983 2984 2985 2986 2987
  }
}

/*
  Read 10000 lines at most. If more than 10000 lines, continue to read after using
*/
2988
static int readTagFromCsvFileToMem(SSuperTable  * superTblInfo) {
2989 2990 2991
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
2992

2993 2994
  FILE *fp = fopen(superTblInfo->tagsFile, "r");
  if (fp == NULL) {
2995
    printf("Failed to open tags file: %s, reason:%s\n",
2996
            superTblInfo->tagsFile, strerror(errno));
2997 2998 2999 3000 3001 3002 3003
    return -1;
  }

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

3005 3006 3007 3008 3009 3010 3011 3012 3013
  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;
  }

3014
  while((readLen = tgetline(&line, &n, fp)) != -1) {
3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026
    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) {
3027
      char *tmp = realloc(tagDataBuf,
3028
              (size_t)tagCount*1.5*superTblInfo->lenOfTagOfOneRow);
3029 3030 3031
      if (tmp != NULL) {
        tagDataBuf = tmp;
        tagCount = (int)(tagCount*1.5);
3032
        memset(tagDataBuf + count*superTblInfo->lenOfTagOfOneRow,
3033
                0, (size_t)((tagCount-count)*superTblInfo->lenOfTagOfOneRow));
3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060
      } 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
*/
3061
static int readSampleFromCsvFileToMem(
3062
        SSuperTable* superTblInfo) {
3063 3064 3065 3066
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
  int getRows = 0;
3067

3068 3069
  FILE*  fp = fopen(superTblInfo->sampleFile, "r");
  if (fp == NULL) {
3070 3071 3072
      errorPrint( "Failed to open sample file: %s, reason:%s\n",
              superTblInfo->sampleFile, strerror(errno));
      return -1;
3073
  }
3074

3075
  assert(superTblInfo->sampleDataBuf);
3076
  memset(superTblInfo->sampleDataBuf, 0,
3077
          MAX_SAMPLES_ONCE_FROM_FILE * superTblInfo->lenOfOneRow);
3078
  while(1) {
3079
    readLen = tgetline(&line, &n, fp);
3080 3081
    if (-1 == readLen) {
      if(0 != fseek(fp, 0, SEEK_SET)) {
3082
        errorPrint( "Failed to fseek file: %s, reason:%s\n",
3083
                superTblInfo->sampleFile, strerror(errno));
3084
        fclose(fp);
3085 3086 3087 3088
        return -1;
      }
      continue;
    }
3089

3090 3091 3092 3093 3094 3095 3096 3097 3098
    if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
      line[--readLen] = 0;
    }

    if (readLen == 0) {
      continue;
    }

    if (readLen > superTblInfo->lenOfOneRow) {
3099
      printf("sample row len[%d] overflow define schema len[%"PRIu64"], so discard this row\n",
3100
              (int32_t)readLen, superTblInfo->lenOfOneRow);
3101 3102 3103
      continue;
    }

3104
    memcpy(superTblInfo->sampleDataBuf + getRows * superTblInfo->lenOfOneRow,
3105
          line, readLen);
3106 3107 3108 3109 3110 3111 3112
    getRows++;

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

3113
  fclose(fp);
3114 3115 3116 3117
  tmfree(line);
  return 0;
}

3118
static bool getColumnAndTagTypeFromInsertJsonFile(
3119
        cJSON* stbInfo, SSuperTable* superTbls) {
3120
  bool  ret = false;
3121

3122
  // columns
3123 3124
  cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns");
  if (columns && columns->type != cJSON_Array) {
3125
    printf("ERROR: failed to read json, columns not found\n");
3126 3127 3128 3129 3130 3131
    goto PARSE_OVER;
  } else if (NULL == columns) {
    superTbls->columnCount = 0;
    superTbls->tagCount    = 0;
    return true;
  }
3132

3133
  int columnSize = cJSON_GetArraySize(columns);
3134
  if ((columnSize + 1/* ts */) > MAX_COLUMN_COUNT) {
3135
    errorPrint("%s() LN%d, failed to read json, column size overflow, max column size is %d\n",
3136
            __func__, __LINE__, MAX_COLUMN_COUNT);
3137 3138 3139 3140 3141 3142
    goto PARSE_OVER;
  }

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

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

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

3173 3174
    cJSON* dataLen = cJSON_GetObjectItem(column, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3175
      columnCase.dataLen = dataLen->valueint;
3176
    } else if (dataLen && dataLen->type != cJSON_Number) {
3177
      debugPrint("%s() LN%d: failed to read json, column len not found\n",
3178
          __func__, __LINE__);
3179 3180 3181 3182
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 8;
    }
3183

3184
    for (int n = 0; n < count; ++n) {
3185
      tstrncpy(superTbls->columns[index].dataType,
3186
              columnCase.dataType, MAX_TB_NAME_SIZE);
3187
      superTbls->columns[index].dataLen = columnCase.dataLen;
3188 3189
      index++;
    }
3190
  }
3191

3192 3193
  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",
3194
            __func__, __LINE__, MAX_COLUMN_COUNT);
3195 3196 3197
    goto PARSE_OVER;
  }

3198
  superTbls->columnCount = index;
3199

3200 3201
  count = 1;
  index = 0;
3202
  // tags
3203 3204
  cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags");
  if (!tags || tags->type != cJSON_Array) {
3205
    errorPrint("%s() LN%d, failed to read json, tags not found\n",
3206
        __func__, __LINE__);
3207 3208
    goto PARSE_OVER;
  }
3209

3210 3211
  int tagSize = cJSON_GetArraySize(tags);
  if (tagSize > MAX_TAG_COUNT) {
3212
    errorPrint("%s() LN%d, failed to read json, tags size overflow, max tag size is %d\n",
3213
        __func__, __LINE__, MAX_TAG_COUNT);
3214 3215
    goto PARSE_OVER;
  }
3216 3217

  //superTbls->tagCount = tagSize;
3218 3219 3220
  for (int k = 0; k < tagSize; ++k) {
    cJSON* tag = cJSON_GetArrayItem(tags, k);
    if (tag == NULL) continue;
3221

3222 3223 3224
    count = 1;
    cJSON* countObj = cJSON_GetObjectItem(tag, "count");
    if (countObj && countObj->type == cJSON_Number) {
3225
      count = countObj->valueint;
3226
    } else if (countObj && countObj->type != cJSON_Number) {
3227
      printf("ERROR: failed to read json, column count not found\n");
3228 3229 3230 3231 3232
      goto PARSE_OVER;
    } else {
      count = 1;
    }

3233
    // column info
3234 3235
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(tag, "type");
3236 3237 3238
    if (!dataType || dataType->type != cJSON_String
        || dataType->valuestring == NULL) {
      errorPrint("%s() LN%d, failed to read json, tag type not found\n",
3239
          __func__, __LINE__);
3240 3241
      goto PARSE_OVER;
    }
3242
    tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
3243

3244 3245
    cJSON* dataLen = cJSON_GetObjectItem(tag, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3246
      columnCase.dataLen = dataLen->valueint;
3247
    } else if (dataLen && dataLen->type != cJSON_Number) {
3248
      errorPrint("%s() LN%d, failed to read json, column len not found\n",
3249
          __func__, __LINE__);
3250 3251 3252
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 0;
3253 3254
    }

3255
    for (int n = 0; n < count; ++n) {
3256
      tstrncpy(superTbls->tags[index].dataType, columnCase.dataType,
3257
          MAX_TB_NAME_SIZE);
3258
      superTbls->tags[index].dataLen = columnCase.dataLen;
3259 3260
      index++;
    }
3261
  }
3262 3263

  if (index > MAX_TAG_COUNT) {
3264
    errorPrint("%s() LN%d, failed to read json, tags size overflow, allowed max tag count is %d\n",
3265
        __func__, __LINE__, MAX_TAG_COUNT);
3266 3267 3268
    goto PARSE_OVER;
  }

3269 3270
  superTbls->tagCount = index;

3271 3272
  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",
3273
        __func__, __LINE__, MAX_COLUMN_COUNT);
3274 3275
    goto PARSE_OVER;
  }
3276 3277
  ret = true;

3278
PARSE_OVER:
3279 3280 3281 3282 3283 3284 3285 3286
  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) {
3287
    tstrncpy(g_Dbs.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3288 3289 3290 3291
  }

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

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
3316
    tstrncpy(g_Dbs.password, password->valuestring, MAX_PASSWORD_SIZE);
3317
  } else if (!password) {
3318
    tstrncpy(g_Dbs.password, "taosdata", MAX_PASSWORD_SIZE);
3319 3320 3321 3322
  }

  cJSON* resultfile = cJSON_GetObjectItem(root, "result_file");
  if (resultfile && resultfile->type == cJSON_String && resultfile->valuestring != NULL) {
3323
    tstrncpy(g_Dbs.resultFile, resultfile->valuestring, MAX_FILE_NAME_LEN);
3324
  } else if (!resultfile) {
3325
    tstrncpy(g_Dbs.resultFile, "./insert_res.txt", MAX_FILE_NAME_LEN);
3326 3327 3328 3329 3330 3331 3332 3333
  }

  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 {
3334
    printf("ERROR: failed to read json, threads not found\n");
3335
    goto PARSE_OVER;
3336 3337
  }

3338 3339 3340 3341
  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 已提交
3342
    g_Dbs.threadCountByCreateTbl = 1;
3343
  } else {
3344
    errorPrint("%s() LN%d, failed to read json, threads2 not found\n",
3345
            __func__, __LINE__);
3346
    goto PARSE_OVER;
3347
  }
3348

3349 3350
  cJSON* gInsertInterval = cJSON_GetObjectItem(root, "insert_interval");
  if (gInsertInterval && gInsertInterval->type == cJSON_Number) {
3351 3352 3353 3354 3355
    if (gInsertInterval->valueint <0) {
      errorPrint("%s() LN%d, failed to read json, insert interval input mistake\n",
            __func__, __LINE__);
      goto PARSE_OVER;
    }
3356 3357 3358 3359
    g_args.insert_interval = gInsertInterval->valueint;
  } else if (!gInsertInterval) {
    g_args.insert_interval = 0;
  } else {
3360
    errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
3361
        __func__, __LINE__);
3362 3363
    goto PARSE_OVER;
  }
3364

3365 3366
  cJSON* interlaceRows = cJSON_GetObjectItem(root, "interlace_rows");
  if (interlaceRows && interlaceRows->type == cJSON_Number) {
3367 3368 3369 3370 3371 3372
    if (interlaceRows->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;

    }
3373
    g_args.interlace_rows = interlaceRows->valueint;
3374 3375 3376

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

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

  cJSON* numRecPerReq = cJSON_GetObjectItem(root, "num_of_records_per_req");
  if (numRecPerReq && numRecPerReq->type == cJSON_Number) {
3411
    if (numRecPerReq->valueint <= 0) {
3412 3413 3414 3415
      errorPrint("%s() LN%d, failed to read json, num_of_records_per_req input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;
    }
3416 3417
    g_args.num_of_RPR = numRecPerReq->valueint;
  } else if (!numRecPerReq) {
3418
    g_args.num_of_RPR = UINT64_MAX;
3419
  } else {
3420
    errorPrint("%s() LN%d, failed to read json, num_of_records_per_req not found\n",
3421
        __func__, __LINE__);
3422 3423 3424
    goto PARSE_OVER;
  }

3425
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
3426
  if (answerPrompt
3427 3428
          && answerPrompt->type == cJSON_String
          && answerPrompt->valuestring != NULL) {
3429 3430 3431 3432 3433 3434 3435 3436 3437 3438
    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 {
3439
    printf("ERROR: failed to read json, confirm_parameter_prompt not found\n");
3440
    goto PARSE_OVER;
3441
  }
3442 3443 3444

  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (!dbs || dbs->type != cJSON_Array) {
3445
    printf("ERROR: failed to read json, databases not found\n");
3446 3447 3448 3449 3450
    goto PARSE_OVER;
  }

  int dbSize = cJSON_GetArraySize(dbs);
  if (dbSize > MAX_DB_COUNT) {
3451
    errorPrint(
3452 3453
            "ERROR: failed to read json, databases size overflow, max database is %d\n",
            MAX_DB_COUNT);
3454 3455 3456 3457 3458 3459 3460 3461
    goto PARSE_OVER;
  }

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

3462
    // dbinfo
3463 3464
    cJSON *dbinfo = cJSON_GetObjectItem(dbinfos, "dbinfo");
    if (!dbinfo || dbinfo->type != cJSON_Object) {
3465
      printf("ERROR: failed to read json, dbinfo not found\n");
3466 3467
      goto PARSE_OVER;
    }
3468

3469 3470
    cJSON *dbName = cJSON_GetObjectItem(dbinfo, "name");
    if (!dbName || dbName->type != cJSON_String || dbName->valuestring == NULL) {
3471
      printf("ERROR: failed to read json, db name not found\n");
3472 3473
      goto PARSE_OVER;
    }
3474
    tstrncpy(g_Dbs.db[i].dbName, dbName->valuestring, MAX_DB_NAME_SIZE);
3475 3476 3477

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

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

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

3544 3545 3546 3547 3548 3549
    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 {
3550 3551
     printf("ERROR: failed to read json, cache not found\n");
     goto PARSE_OVER;
3552
    }
3553

3554 3555 3556 3557 3558 3559
    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 {
3560 3561
     printf("ERROR: failed to read json, block not found\n");
     goto PARSE_OVER;
3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577
    }

    //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) {
3578
      g_Dbs.db[i].dbCfg.minRows = 0;    // 0 means default
3579
    } else {
3580 3581
     printf("ERROR: failed to read json, minRows not found\n");
     goto PARSE_OVER;
3582 3583 3584 3585 3586 3587
    }

    cJSON* maxRows= cJSON_GetObjectItem(dbinfo, "maxRows");
    if (maxRows && maxRows->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.maxRows = maxRows->valueint;
    } else if (!maxRows) {
3588
      g_Dbs.db[i].dbCfg.maxRows = 0;    // 0 means default
3589
    } else {
3590 3591
     printf("ERROR: failed to read json, maxRows not found\n");
     goto PARSE_OVER;
3592 3593 3594 3595 3596 3597 3598 3599
    }

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

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

3614 3615 3616 3617 3618 3619
    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 {
3620 3621
     printf("ERROR: failed to read json, cacheLast not found\n");
     goto PARSE_OVER;
3622 3623
    }

3624 3625 3626 3627
    cJSON* quorum= cJSON_GetObjectItem(dbinfo, "quorum");
    if (quorum && quorum->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.quorum = quorum->valueint;
    } else if (!quorum) {
3628
      g_Dbs.db[i].dbCfg.quorum = 1;
3629
    } else {
3630 3631
     printf("failed to read json, quorum input mistake");
     goto PARSE_OVER;
3632 3633 3634 3635 3636 3637 3638 3639
    }

    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 {
3640
      errorPrint("%s() LN%d, failed to read json, fsync input mistake\n",
3641
              __func__, __LINE__);
3642
      goto PARSE_OVER;
3643
    }
3644

3645
    // super_talbes
3646 3647
    cJSON *stables = cJSON_GetObjectItem(dbinfos, "super_tables");
    if (!stables || stables->type != cJSON_Array) {
3648
      errorPrint("%s() LN%d, failed to read json, super_tables not found\n",
3649
              __func__, __LINE__);
3650
      goto PARSE_OVER;
3651 3652
    }

3653 3654
    int stbSize = cJSON_GetArraySize(stables);
    if (stbSize > MAX_SUPER_TABLE_COUNT) {
3655
      errorPrint(
3656 3657
              "%s() LN%d, failed to read json, supertable size overflow, max supertable is %d\n",
              __func__, __LINE__, MAX_SUPER_TABLE_COUNT);
3658 3659 3660 3661 3662 3663 3664
      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;
3665 3666

      // dbinfo
3667 3668
      cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name");
      if (!stbName || stbName->type != cJSON_String || stbName->valuestring == NULL) {
3669
        errorPrint("%s() LN%d, failed to read json, stb name not found\n",
3670
                __func__, __LINE__);
3671 3672
        goto PARSE_OVER;
      }
3673
      tstrncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring, MAX_TB_NAME_SIZE);
3674

3675 3676
      cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix");
      if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) {
3677
        printf("ERROR: failed to read json, childtable_prefix not found\n");
3678 3679
        goto PARSE_OVER;
      }
3680
      tstrncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring, MAX_DB_NAME_SIZE);
3681 3682

      cJSON *autoCreateTbl = cJSON_GetObjectItem(stbInfo, "auto_create_table"); // yes, no, null
3683
      if (autoCreateTbl
3684 3685
              && autoCreateTbl->type == cJSON_String
              && autoCreateTbl->valuestring != NULL) {
3686 3687 3688 3689 3690 3691 3692 3693 3694 3695
        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 {
3696
        printf("ERROR: failed to read json, auto_create_table not found\n");
3697 3698
        goto PARSE_OVER;
      }
3699

3700 3701 3702 3703
      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) {
3704
        g_Dbs.db[i].superTbls[j].batchCreateTableNum = 1000;
3705
      } else {
3706
        printf("ERROR: failed to read json, batch_create_tbl_num not found\n");
3707
        goto PARSE_OVER;
3708
      }
3709 3710

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

3731 3732
      cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count");
      if (!count || count->type != cJSON_Number || 0 >= count->valueint) {
3733
        errorPrint("%s() LN%d, failed to read json, childtable_count input mistake\n",
3734
                __func__, __LINE__);
3735 3736 3737 3738 3739
        goto PARSE_OVER;
      }
      g_Dbs.db[i].superTbls[j].childTblCount = count->valueint;

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

3752
      cJSON *insertMode = cJSON_GetObjectItem(stbInfo, "insert_mode"); // taosc , rest
3753
      if (insertMode && insertMode->type == cJSON_String
3754
              && insertMode->valuestring != NULL) {
3755
        tstrncpy(g_Dbs.db[i].superTbls[j].insertMode,
3756
                insertMode->valuestring, MAX_DB_NAME_SIZE);
3757
      } else if (!insertMode) {
3758
        tstrncpy(g_Dbs.db[i].superTbls[j].insertMode, "taosc", MAX_DB_NAME_SIZE);
3759
      } else {
3760
        printf("ERROR: failed to read json, insert_mode not found\n");
3761 3762 3763
        goto PARSE_OVER;
      }

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

      cJSON* childTbl_offset = cJSON_GetObjectItem(stbInfo, "childtable_offset");
3777 3778
      if ((childTbl_offset) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
3779
        if (childTbl_offset->type != cJSON_Number || 0 > childTbl_offset->valueint) {
3780 3781
            printf("ERROR: failed to read json, childtable_offset\n");
            goto PARSE_OVER;
3782 3783 3784 3785 3786 3787
        }
        g_Dbs.db[i].superTbls[j].childTblOffset = childTbl_offset->valueint;
      } else {
        g_Dbs.db[i].superTbls[j].childTblOffset = 0;
      }

3788 3789
      cJSON *ts = cJSON_GetObjectItem(stbInfo, "start_timestamp");
      if (ts && ts->type == cJSON_String && ts->valuestring != NULL) {
3790
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
3791
                ts->valuestring, MAX_DB_NAME_SIZE);
3792
      } else if (!ts) {
3793
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
3794
                "now", MAX_DB_NAME_SIZE);
3795
      } else {
3796
        printf("ERROR: failed to read json, start_timestamp not found\n");
3797 3798
        goto PARSE_OVER;
      }
3799

3800 3801 3802 3803
      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) {
3804
        g_Dbs.db[i].superTbls[j].timeStampStep = DEFAULT_TIMESTAMP_STEP;
3805
      } else {
3806
        printf("ERROR: failed to read json, timestamp_step not found\n");
3807 3808 3809 3810
        goto PARSE_OVER;
      }

      cJSON *sampleFormat = cJSON_GetObjectItem(stbInfo, "sample_format");
3811
      if (sampleFormat && sampleFormat->type
3812
              == cJSON_String && sampleFormat->valuestring != NULL) {
3813
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat,
3814
                sampleFormat->valuestring, MAX_DB_NAME_SIZE);
3815
      } else if (!sampleFormat) {
3816
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat, "csv", MAX_DB_NAME_SIZE);
3817
      } else {
3818
        printf("ERROR: failed to read json, sample_format not found\n");
3819
        goto PARSE_OVER;
3820
      }
3821

3822
      cJSON *sampleFile = cJSON_GetObjectItem(stbInfo, "sample_file");
3823 3824
      if (sampleFile && sampleFile->type == cJSON_String
          && sampleFile->valuestring != NULL) {
3825
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFile,
3826
                sampleFile->valuestring, MAX_FILE_NAME_LEN);
3827 3828 3829
      } else if (!sampleFile) {
        memset(g_Dbs.db[i].superTbls[j].sampleFile, 0, MAX_FILE_NAME_LEN);
      } else {
3830
        printf("ERROR: failed to read json, sample_file not found\n");
3831
        goto PARSE_OVER;
3832
      }
3833

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

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

      cJSON* disorderRatio = cJSON_GetObjectItem(stbInfo, "disorder_ratio");
      if (disorderRatio && disorderRatio->type == cJSON_Number) {
3914 3915 3916 3917 3918 3919
        if (disorderRatio->valueint > 50)
          disorderRatio->valueint = 50;

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

3920 3921 3922 3923
        g_Dbs.db[i].superTbls[j].disorderRatio = disorderRatio->valueint;
      } else if (!disorderRatio) {
        g_Dbs.db[i].superTbls[j].disorderRatio = 0;
      } else {
3924
        printf("ERROR: failed to read json, disorderRatio not found\n");
3925
        goto PARSE_OVER;
3926
      }
3927 3928 3929 3930 3931 3932 3933

      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 {
3934
        printf("ERROR: failed to read json, disorderRange not found\n");
3935 3936
        goto PARSE_OVER;
      }
3937

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

3972
      int retVal = getColumnAndTagTypeFromInsertJsonFile(
3973
              stbInfo, &g_Dbs.db[i].superTbls[j]);
3974 3975
      if (false == retVal) {
        goto PARSE_OVER;
3976 3977
      }
    }
3978 3979 3980 3981
  }

  ret = true;

3982
PARSE_OVER:
3983 3984 3985 3986 3987 3988 3989 3990
  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) {
3991
    tstrncpy(g_queryInfo.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3992 3993 3994 3995
  }

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

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
4020
    tstrncpy(g_queryInfo.password, password->valuestring, MAX_PASSWORD_SIZE);
4021
  } else if (!password) {
4022
    tstrncpy(g_queryInfo.password, "taosdata", MAX_PASSWORD_SIZE);;
4023
  }
H
hzcheng 已提交
4024

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

4042 4043
  cJSON* gQueryTimes = cJSON_GetObjectItem(root, "query_times");
  if (gQueryTimes && gQueryTimes->type == cJSON_Number) {
4044 4045 4046
    if (gQueryTimes->valueint <= 0) {
      errorPrint("%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
        __func__, __LINE__, gQueryTimes->valueint);
4047 4048
      goto PARSE_OVER;
    }
4049 4050 4051 4052
    g_args.query_times = gQueryTimes->valueint;
  } else if (!gQueryTimes) {
    g_args.query_times = 1;
  } else {
4053
    errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4054
        __func__, __LINE__);
4055 4056 4057
    goto PARSE_OVER;
  }

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

  cJSON* queryMode = cJSON_GetObjectItem(root, "query_mode");
  if (queryMode && queryMode->type == cJSON_String && queryMode->valuestring != NULL) {
4068
    tstrncpy(g_queryInfo.queryMode, queryMode->valuestring, MAX_TB_NAME_SIZE);
4069
  } else if (!queryMode) {
4070
    tstrncpy(g_queryInfo.queryMode, "taosc", MAX_TB_NAME_SIZE);
4071
  } else {
4072
    printf("ERROR: failed to read json, query_mode not found\n");
4073
    goto PARSE_OVER;
H
hzcheng 已提交
4074
  }
4075

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

4092
    cJSON* specifiedQueryTimes = cJSON_GetObjectItem(specifiedQuery,
4093
        "query_times");
4094
    if (specifiedQueryTimes && specifiedQueryTimes->type == cJSON_Number) {
4095 4096 4097
      if (specifiedQueryTimes->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
                __func__, __LINE__, specifiedQueryTimes->valueint);
4098 4099 4100
        goto PARSE_OVER;

      }
4101 4102 4103 4104
      g_queryInfo.specifiedQueryInfo.queryTimes = specifiedQueryTimes->valueint;
    } else if (!specifiedQueryTimes) {
      g_queryInfo.specifiedQueryInfo.queryTimes = g_args.query_times;
    } else {
4105
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4106
          __func__, __LINE__);
4107
      goto PARSE_OVER;
4108
    }
4109

4110
    cJSON* concurrent = cJSON_GetObjectItem(specifiedQuery, "concurrent");
4111
    if (concurrent && concurrent->type == cJSON_Number) {
4112 4113 4114 4115
      if (concurrent->valueint <= 0) {
        errorPrint("%s() LN%d, query sqlCount %"PRIu64" or concurrent %"PRIu64" is not correct.\n",
              __func__, __LINE__,
              g_queryInfo.specifiedQueryInfo.sqlCount,
4116
              g_queryInfo.specifiedQueryInfo.concurrent);
4117 4118
        goto PARSE_OVER;
      }
4119
      g_queryInfo.specifiedQueryInfo.concurrent = concurrent->valueint;
4120
    } else if (!concurrent) {
4121
      g_queryInfo.specifiedQueryInfo.concurrent = 1;
4122
    }
4123

4124 4125 4126 4127
    cJSON* mode = cJSON_GetObjectItem(specifiedQuery, "mode");
    if (mode && mode->type == cJSON_String
        && mode->valuestring != NULL) {
      if (0 == strcmp("sync", mode->valuestring)) {
4128
        g_queryInfo.specifiedQueryInfo.mode = SYNC_QUERY_MODE;
4129
      } else if (0 == strcmp("async", mode->valuestring)) {
4130
        g_queryInfo.specifiedQueryInfo.mode = ASYNC_QUERY_MODE;
4131
      } else {
4132
        errorPrint("%s() LN%d, failed to read json, query mode input error\n",
4133
            __func__, __LINE__);
4134 4135 4136
        goto PARSE_OVER;
      }
    } else {
4137
      g_queryInfo.specifiedQueryInfo.mode = SYNC_QUERY_MODE;
4138
    }
4139

4140
    cJSON* interval = cJSON_GetObjectItem(specifiedQuery, "interval");
4141
    if (interval && interval->type == cJSON_Number) {
4142
      g_queryInfo.specifiedQueryInfo.subscribeInterval = interval->valueint;
4143
    } else if (!interval) {
4144 4145
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4146
      g_queryInfo.specifiedQueryInfo.subscribeInterval = 10000;
4147
    }
4148

4149
    cJSON* restart = cJSON_GetObjectItem(specifiedQuery, "restart");
4150
    if (restart && restart->type == cJSON_String && restart->valuestring != NULL) {
4151
      if (0 == strcmp("yes", restart->valuestring)) {
4152
        g_queryInfo.specifiedQueryInfo.subscribeRestart = 1;
4153
      } else if (0 == strcmp("no", restart->valuestring)) {
4154
        g_queryInfo.specifiedQueryInfo.subscribeRestart = 0;
4155
      } else {
4156
        printf("ERROR: failed to read json, subscribe restart error\n");
4157 4158 4159
        goto PARSE_OVER;
      }
    } else {
4160
      g_queryInfo.specifiedQueryInfo.subscribeRestart = 1;
4161
    }
4162

4163
    cJSON* keepProgress = cJSON_GetObjectItem(specifiedQuery, "keepProgress");
4164
    if (keepProgress
4165 4166
            && keepProgress->type == cJSON_String
            && keepProgress->valuestring != NULL) {
4167
      if (0 == strcmp("yes", keepProgress->valuestring)) {
4168
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 1;
4169
      } else if (0 == strcmp("no", keepProgress->valuestring)) {
4170
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4171
      } else {
4172
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
4173 4174 4175
        goto PARSE_OVER;
      }
    } else {
4176
      g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4177 4178
    }

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

4195
      g_queryInfo.specifiedQueryInfo.sqlCount = superSqlSize;
4196 4197 4198
      for (int j = 0; j < superSqlSize; ++j) {
        cJSON* sql = cJSON_GetArrayItem(superSqls, j);
        if (sql == NULL) continue;
4199

4200 4201
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
        if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) {
4202
          printf("ERROR: failed to read json, sql not found\n");
4203 4204
          goto PARSE_OVER;
        }
4205
        tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH);
H
hzcheng 已提交
4206

4207 4208
        cJSON *result = cJSON_GetObjectItem(sql, "result");
        if (NULL != result && result->type == cJSON_String && result->valuestring != NULL) {
4209
          tstrncpy(g_queryInfo.specifiedQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN);
4210
        } else if (NULL == result) {
4211
          memset(g_queryInfo.specifiedQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
4212
        } else {
4213
          printf("ERROR: failed to read json, super query result file not found\n");
4214
          goto PARSE_OVER;
4215
        }
4216 4217 4218
      }
    }
  }
4219

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

    cJSON* superQueryTimes = cJSON_GetObjectItem(superQuery, "query_times");
    if (superQueryTimes && superQueryTimes->type == cJSON_Number) {
4239 4240 4241
      if (superQueryTimes->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
                __func__, __LINE__, superQueryTimes->valueint);
4242 4243
        goto PARSE_OVER;
      }
4244 4245 4246 4247
      g_queryInfo.superQueryInfo.queryTimes = superQueryTimes->valueint;
    } else if (!superQueryTimes) {
      g_queryInfo.superQueryInfo.queryTimes = g_args.query_times;
    } else {
4248
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4249
          __func__, __LINE__);
4250
      goto PARSE_OVER;
4251
    }
4252

4253
    cJSON* threads = cJSON_GetObjectItem(superQuery, "threads");
4254
    if (threads && threads->type == cJSON_Number) {
4255 4256 4257 4258 4259 4260
      if (threads->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, threads input mistake\n",
          __func__, __LINE__);
        goto PARSE_OVER;

      }
4261
      g_queryInfo.superQueryInfo.threadCnt = threads->valueint;
4262
    } else if (!threads) {
4263
      g_queryInfo.superQueryInfo.threadCnt = 1;
4264
    }
4265

4266
    //cJSON* subTblCnt = cJSON_GetObjectItem(superQuery, "childtable_count");
4267
    //if (subTblCnt && subTblCnt->type == cJSON_Number) {
4268
    //  g_queryInfo.superQueryInfo.childTblCount = subTblCnt->valueint;
4269
    //} else if (!subTblCnt) {
4270
    //  g_queryInfo.superQueryInfo.childTblCount = 0;
4271
    //}
4272

4273
    cJSON* stblname = cJSON_GetObjectItem(superQuery, "stblname");
4274 4275 4276
    if (stblname && stblname->type == cJSON_String
        && stblname->valuestring != NULL) {
      tstrncpy(g_queryInfo.superQueryInfo.sTblName, stblname->valuestring,
4277
          MAX_TB_NAME_SIZE);
4278
    } else {
4279
      errorPrint("%s() LN%d, failed to read json, super table name input error\n",
4280
          __func__, __LINE__);
4281 4282
      goto PARSE_OVER;
    }
4283

4284
    cJSON* submode = cJSON_GetObjectItem(superQuery, "mode");
4285 4286
    if (submode && submode->type == cJSON_String
        && submode->valuestring != NULL) {
4287
      if (0 == strcmp("sync", submode->valuestring)) {
4288
        g_queryInfo.superQueryInfo.mode = SYNC_QUERY_MODE;
4289
      } else if (0 == strcmp("async", submode->valuestring)) {
4290
        g_queryInfo.superQueryInfo.mode = ASYNC_QUERY_MODE;
4291
      } else {
4292
        errorPrint("%s() LN%d, failed to read json, query mode input error\n",
4293
            __func__, __LINE__);
4294 4295 4296
        goto PARSE_OVER;
      }
    } else {
4297
      g_queryInfo.superQueryInfo.mode = SYNC_QUERY_MODE;
4298
    }
4299

4300 4301 4302 4303 4304 4305 4306 4307 4308
    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) {
4309 4310
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4311
      g_queryInfo.superQueryInfo.subscribeInterval = 10000;
4312
    }
4313

4314
    cJSON* subrestart = cJSON_GetObjectItem(superQuery, "restart");
4315 4316
    if (subrestart && subrestart->type == cJSON_String
        && subrestart->valuestring != NULL) {
4317
      if (0 == strcmp("yes", subrestart->valuestring)) {
4318
        g_queryInfo.superQueryInfo.subscribeRestart = 1;
4319
      } else if (0 == strcmp("no", subrestart->valuestring)) {
4320
        g_queryInfo.superQueryInfo.subscribeRestart = 0;
4321
      } else {
4322
        printf("ERROR: failed to read json, subscribe restart error\n");
4323 4324 4325
        goto PARSE_OVER;
      }
    } else {
4326
      g_queryInfo.superQueryInfo.subscribeRestart = 1;
4327
    }
4328

4329
    cJSON* subkeepProgress = cJSON_GetObjectItem(superQuery, "keepProgress");
4330
    if (subkeepProgress &&
4331 4332
            subkeepProgress->type == cJSON_String
            && subkeepProgress->valuestring != NULL) {
4333
      if (0 == strcmp("yes", subkeepProgress->valuestring)) {
4334
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 1;
4335
      } else if (0 == strcmp("no", subkeepProgress->valuestring)) {
4336
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4337
      } else {
4338
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
4339 4340 4341
        goto PARSE_OVER;
      }
    } else {
4342
      g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4343
    }
4344

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

4361
      g_queryInfo.superQueryInfo.sqlCount = superSqlSize;
4362
      for (int j = 0; j < superSqlSize; ++j) {
4363 4364
        cJSON* sql = cJSON_GetArrayItem(subsqls, j);
        if (sql == NULL) continue;
4365

4366
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
4367 4368 4369
        if (!sqlStr || sqlStr->type != cJSON_String
            || sqlStr->valuestring == NULL) {
          errorPrint("%s() LN%d, failed to read json, sql not found\n",
4370
              __func__, __LINE__);
4371 4372
          goto PARSE_OVER;
        }
4373
        tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring,
4374
            MAX_QUERY_SQL_LENGTH);
4375 4376

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

4392
  ret = true;
H
hzcheng 已提交
4393

4394
PARSE_OVER:
4395 4396
  return ret;
}
H
hzcheng 已提交
4397

4398
static bool getInfoFromJsonFile(char* file) {
4399
    debugPrint("%s %d %s\n", __func__, __LINE__, file);
4400

4401 4402 4403 4404 4405
  FILE *fp = fopen(file, "r");
  if (!fp) {
    printf("failed to read %s, reason:%s\n", file, strerror(errno));
    return false;
  }
H
Hui Li 已提交
4406

4407
  bool  ret = false;
4408
  int   maxLen = 6400000;
4409 4410 4411 4412 4413 4414 4415
  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 已提交
4416
  }
H
Hui Li 已提交
4417

4418 4419 4420
  content[len] = 0;
  cJSON* root = cJSON_Parse(content);
  if (root == NULL) {
4421
    printf("ERROR: failed to cjson parse %s, invalid json format\n", file);
4422 4423
    goto PARSE_OVER;
  }
H
Hui Li 已提交
4424

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

4444
  if (INSERT_TEST == g_args.test_mode) {
4445
    ret = getMetaFromInsertJsonFile(root);
4446
  } else if ((QUERY_TEST == g_args.test_mode)
4447
          || (SUBSCRIBE_TEST == g_args.test_mode)) {
4448 4449
    ret = getMetaFromQueryJsonFile(root);
  } else {
4450
    errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n",
4451
            __func__, __LINE__);
4452
    goto PARSE_OVER;
4453
  }
4454

4455
PARSE_OVER:
4456 4457
  free(content);
  cJSON_Delete(root);
H
hzcheng 已提交
4458
  fclose(fp);
4459 4460
  return ret;
}
H
hzcheng 已提交
4461

4462
static void prepareSampleData() {
4463
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4464 4465 4466
    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 已提交
4467
      }
4468 4469 4470 4471
    }
  }
}

4472
static void postFreeResource() {
4473
  tmfclose(g_fpOfInsertResult);
4474
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4475
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
4476 4477 4478
      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 已提交
4479
      }
4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491
      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 已提交
4492
    }
4493 4494
  }
}
S
Shuaiqiang Chang 已提交
4495

4496 4497 4498
static int getRowDataFromSample(
        char* dataBuf, int64_t maxLen, int64_t timestamp,
      SSuperTable* superTblInfo, int64_t* sampleUsePos) {
4499
  if ((*sampleUsePos) == MAX_SAMPLES_ONCE_FROM_FILE) {
4500
/*    int ret = readSampleFromCsvFileToMem(superTblInfo);
4501
    if (0 != ret) {
4502
      tmfree(superTblInfo->sampleDataBuf);
4503
      superTblInfo->sampleDataBuf = NULL;
4504 4505
      return -1;
    }
4506
*/
4507 4508
    *sampleUsePos = 0;
  }
S
Shuaiqiang Chang 已提交
4509

4510
  int    dataLen = 0;
4511

4512
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
4513
          "(%" PRId64 ", ", timestamp);
4514
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
4515
          "%s", superTblInfo->sampleDataBuf + superTblInfo->lenOfOneRow * (*sampleUsePos));
4516
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");
S
Shuaiqiang Chang 已提交
4517

4518
  (*sampleUsePos)++;
4519

4520 4521
  return dataLen;
}
S
Shuaiqiang Chang 已提交
4522

4523 4524
static int64_t generateRowData(char* recBuf, int64_t timestamp, SSuperTable* stbInfo) {
  int64_t   dataLen = 0;
4525
  char  *pstr = recBuf;
4526
  int64_t maxLen = MAX_DATA_SIZE;
4527

4528
  dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "(%" PRId64 ",", timestamp);
4529

4530
  for (int i = 0; i < stbInfo->columnCount; i++) {
4531 4532
    if ((0 == strncasecmp(stbInfo->columns[i].dataType, "BINARY", strlen("BINARY")))
            || (0 == strncasecmp(stbInfo->columns[i].dataType, "NCHAR", strlen("NCHAR")))) {
4533
      if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) {
4534
        errorPrint( "binary or nchar length overflow, max size:%u\n",
4535
                (uint32_t)TSDB_MAX_BINARY_LEN);
4536
        return -1;
4537
      }
4538

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

4585
  dataLen -= 1;
4586
  dataLen += snprintf(pstr + dataLen, maxLen - dataLen, ")");
4587

4588 4589 4590
  verbosePrint("%s() LN%d, recBuf:\n\t%s\n", __func__, __LINE__, recBuf);

  return strlen(recBuf);
4591
}
S
Shuaiqiang Chang 已提交
4592

4593
static int64_t generateData(char *recBuf, char **data_type,
4594
        int num_of_cols, int64_t timestamp, int lenOfBinary) {
4595 4596
  memset(recBuf, 0, MAX_DATA_SIZE);
  char *pstr = recBuf;
4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610
  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 已提交
4611
  for (int i = 0; i < c; i++) {
4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622
    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) {
4623
      double t = rand_double();
4624 4625
      pstr += sprintf(pstr, ",%20.8f", t);
    } else if (strcasecmp(data_type[i % c], "BOOL") == 0) {
4626
      bool b = taosRandom() & 1;
4627 4628
      pstr += sprintf(pstr, ",%s", b ? "true" : "false");
    } else if (strcasecmp(data_type[i % c], "BINARY") == 0) {
4629 4630
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4631
      pstr += sprintf(pstr, ",\"%s\"", s);
4632
      free(s);
4633
    } else if (strcasecmp(data_type[i % c], "NCHAR") == 0) {
4634 4635
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4636
      pstr += sprintf(pstr, ",\"%s\"", s);
4637 4638 4639
      free(s);
    }

4640
    if (strlen(recBuf) > MAX_DATA_SIZE) {
4641 4642 4643 4644 4645 4646 4647
      perror("column length too long, abort");
      exit(-1);
    }
  }

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

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

4650
  return (int32_t)strlen(recBuf);
4651 4652
}

4653
static int prepareSampleDataForSTable(SSuperTable *superTblInfo) {
4654 4655
  char* sampleDataBuf = NULL;

4656
  sampleDataBuf = calloc(
4657
            superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1);
4658
  if (sampleDataBuf == NULL) {
4659
      errorPrint("%s() LN%d, Failed to calloc %"PRIu64" Bytes, reason:%s\n",
4660 4661 4662 4663
              __func__, __LINE__,
              superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE,
              strerror(errno));
      return -1;
4664
  }
4665

4666 4667 4668 4669
  superTblInfo->sampleDataBuf = sampleDataBuf;
  int ret = readSampleFromCsvFileToMem(superTblInfo);

  if (0 != ret) {
4670 4671 4672 4673 4674
      errorPrint("%s() LN%d, read sample from csv file failed.\n",
          __func__, __LINE__);
      tmfree(sampleDataBuf);
      superTblInfo->sampleDataBuf = NULL;
      return -1;
H
Hui Li 已提交
4675
  }
4676

4677 4678 4679
  return 0;
}

4680
static int64_t execInsert(threadInfo *pThreadInfo, char *buffer, uint64_t k)
4681 4682
{
  int affectedRows;
4683
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4684

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

  return affectedRows;
}

4710
static void getTableName(char *pTblName, threadInfo* pThreadInfo, uint64_t tableSeq)
4711 4712
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4713
  if (superTblInfo) {
4714
    if (superTblInfo->childTblLimit > 0) {
4715 4716 4717
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
            superTblInfo->childTblName +
            (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN);
4718
    } else {
4719

4720
        verbosePrint("[%d] %s() LN%d: from=%"PRIu64" count=%"PRIu64" seq=%"PRIu64"\n",
4721 4722 4723 4724 4725
                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);
4726 4727
    }
  } else {
4728
    snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"",
4729
        g_args.tb_prefix, tableSeq);
4730 4731 4732
  }
}

4733
static int64_t generateDataTail(
4734
        SSuperTable* superTblInfo,
4735
        uint64_t batch, char* buffer, int64_t remainderBufLen, int64_t insertRows,
4736
        int64_t startFrom, int64_t startTime, int64_t *pSamplePos, int64_t *dataLen) {
4737 4738
  uint64_t len = 0;
  uint32_t ncols_per_record = 1; // count first col ts
4739

4740 4741
  char *pstr = buffer;

4742
  if (superTblInfo == NULL) {
4743
    uint32_t datatypeSeq = 0;
4744
    while(g_args.datatype[datatypeSeq]) {
4745 4746
        datatypeSeq ++;
        ncols_per_record ++;
4747
    }
4748 4749
  }

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

4752
  uint64_t k = 0;
4753
  for (k = 0; k < batch;) {
4754
    char data[MAX_DATA_SIZE];
4755 4756
    memset(data, 0, MAX_DATA_SIZE);

4757
    int64_t retLen = 0;
4758

4759 4760
    if (superTblInfo) {
      if (0 == strncasecmp(superTblInfo->dataSource,
4761 4762 4763 4764 4765 4766 4767
                    "sample", strlen("sample"))) {
          retLen = getRowDataFromSample(
                    data,
                    remainderBufLen,
                    startTime + superTblInfo->timeStampStep * k,
                    superTblInfo,
                    pSamplePos);
4768
      } else if (0 == strncasecmp(superTblInfo->dataSource,
4769
                   "rand", strlen("rand"))) {
4770

4771
        int64_t randTail = superTblInfo->timeStampStep * k;
4772 4773 4774 4775
        if (superTblInfo->disorderRatio > 0) {
          int rand_num = taosRandom() % 100;
          if(rand_num < superTblInfo->disorderRatio) {
            randTail = (randTail + (taosRandom() % superTblInfo->disorderRange + 1)) * (-1);
4776
            debugPrint("rand data generated, back %"PRId64"\n", randTail);
4777
          }
4778 4779
        }

4780
        int64_t d = startTime
4781
                + randTail;
4782
        retLen = generateRowData(
4783 4784 4785
                      data,
                      d,
                      superTblInfo);
4786
      }
4787

4788 4789 4790
      if (retLen > remainderBufLen) {
        break;
      }
4791

4792
      pstr += snprintf(pstr , retLen + 1, "%s", data);
4793 4794 4795
      k++;
      len += retLen;
      remainderBufLen -= retLen;
4796
    } else {
4797 4798
      char **data_type = g_args.datatype;
      int lenOfBinary = g_args.len_of_binary;
4799

4800 4801 4802 4803 4804 4805
      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);
4806

4807 4808
          debugPrint("rand data generated, back %"PRId64"\n", randTail);
        }
4809
      } else {
4810 4811 4812 4813
        randTail = DEFAULT_TIMESTAMP_STEP * k;
      }

      retLen = generateData(data, data_type,
4814 4815 4816
                  ncols_per_record,
                  startTime + randTail,
                  lenOfBinary);
4817

4818 4819 4820
      if (len > remainderBufLen)
        break;

H
Haojun Liao 已提交
4821
      pstr += sprintf(pstr, "%s", data);
4822 4823 4824
      k++;
      len += retLen;
      remainderBufLen -= retLen;
4825 4826
    }

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

    startFrom ++;
4831

4832
    if (startFrom >= insertRows) {
4833
      break;
4834
    }
4835
  }
4836

4837 4838 4839
  *dataLen = len;
  return k;
}
4840

4841
static int generateSQLHead(char *tableName, int32_t tableSeq,
4842 4843
        threadInfo* pThreadInfo, SSuperTable* superTblInfo,
        char *buffer, int remainderBufLen)
4844 4845
{
  int len;
4846 4847 4848 4849

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

4850 4851 4852 4853
  if (superTblInfo) {
    if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) {
      char* tagsValBuf = NULL;
      if (0 == superTblInfo->tagSource) {
4854
            tagsValBuf = generateTagVaulesForStb(superTblInfo, tableSeq);
4855
      } else {
4856 4857 4858
            tagsValBuf = getTagValueFromTagSample(
                    superTblInfo,
                    tableSeq % superTblInfo->tagSampleCount);
4859 4860
      }
      if (NULL == tagsValBuf) {
4861
        errorPrint("%s() LN%d, tag buf failed to allocate  memory\n",
4862
            __func__, __LINE__);
4863 4864 4865
        return -1;
      }

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

4900 4901 4902 4903 4904
  if (len > remainderBufLen)
    return -1;

  tstrncpy(buffer, headBuf, len + 1);

4905 4906 4907
  return len;
}

4908
static int64_t generateInterlaceDataBuffer(
4909 4910
        char *tableName, uint64_t batchPerTbl, uint64_t i, uint64_t batchPerTblTimes,
        uint64_t tableSeq,
4911
        threadInfo *pThreadInfo, char *buffer,
4912
        uint64_t insertRows,
4913
        int64_t startTime,
4914
        uint64_t *pRemainderBufLen)
4915
{
4916
  assert(buffer);
4917 4918 4919 4920
  char *pstr = buffer;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;

  int headLen = generateSQLHead(tableName, tableSeq, pThreadInfo,
4921
            superTblInfo, pstr, *pRemainderBufLen);
4922 4923 4924 4925 4926

  if (headLen <= 0) {
    return 0;
  }
  // generate data buffer
4927
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" buffer:\n%s\n",
4928
            pThreadInfo->threadID, __func__, __LINE__, i, buffer);
4929 4930 4931 4932

  pstr += headLen;
  *pRemainderBufLen -= headLen;

4933
  int64_t dataLen = 0;
4934

4935
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" batchPerTblTimes=%"PRIu64" batchPerTbl = %"PRIu64"\n",
4936 4937
            pThreadInfo->threadID, __func__, __LINE__,
            i, batchPerTblTimes, batchPerTbl);
4938 4939 4940 4941 4942 4943

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

4947
  int64_t k = generateDataTail(
4948 4949 4950 4951
    superTblInfo,
    batchPerTbl, pstr, *pRemainderBufLen, insertRows, 0,
    startTime,
    &(pThreadInfo->samplePos), &dataLen);
4952

4953
  if (k == batchPerTbl) {
4954 4955 4956
    pstr += dataLen;
    *pRemainderBufLen -= dataLen;
  } else {
4957
    debugPrint("%s() LN%d, generated data tail: %"PRIu64", not equal batch per table: %"PRIu64"\n",
4958
            __func__, __LINE__, k, batchPerTbl);
4959 4960
    pstr -= headLen;
    pstr[0] = '\0';
4961
    k = 0;
4962 4963 4964 4965 4966
  }

  return k;
}

4967
static int64_t generateProgressiveDataBuffer(
4968
        char *tableName,
4969
        int64_t tableSeq,
4970 4971
        threadInfo *pThreadInfo, char *buffer,
        int64_t insertRows,
4972 4973
        int64_t startFrom, int64_t startTime, int64_t *pSamplePos,
        int64_t *pRemainderBufLen)
4974 4975 4976 4977 4978 4979 4980 4981
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;

  int ncols_per_record = 1; // count first col ts

  if (superTblInfo == NULL) {
    int datatypeSeq = 0;
    while(g_args.datatype[datatypeSeq]) {
4982 4983
        datatypeSeq ++;
        ncols_per_record ++;
4984 4985 4986 4987
    }
  }

  assert(buffer != NULL);
4988
  char *pstr = buffer;
4989

4990
  int64_t k = 0;
4991

4992
  memset(buffer, 0, *pRemainderBufLen);
4993

4994
  int64_t headLen = generateSQLHead(tableName, tableSeq, pThreadInfo, superTblInfo,
4995
          buffer, *pRemainderBufLen);
4996 4997 4998 4999

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

5003
  int64_t dataLen;
5004
  k = generateDataTail(superTblInfo,
5005 5006 5007
          g_args.num_of_RPR, pstr, *pRemainderBufLen, insertRows, startFrom,
          startTime,
          pSamplePos, &dataLen);
5008

5009 5010
  return k;
}
5011

5012 5013 5014 5015 5016 5017 5018 5019 5020
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)));
}

5021
static void* syncWriteInterlace(threadInfo *pThreadInfo) {
5022
  debugPrint("[%d] %s() LN%d: ### interlace write\n",
5023 5024
         pThreadInfo->threadID, __func__, __LINE__);

5025 5026
  uint64_t insertRows;
  uint64_t interlaceRows;
5027 5028

  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5029

5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042
  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;
  }
5043

5044
  if (interlaceRows > insertRows)
H
Haojun Liao 已提交
5045
    interlaceRows = insertRows;
5046

5047 5048
  if (interlaceRows > g_args.num_of_RPR)
    interlaceRows = g_args.num_of_RPR;
5049

5050 5051 5052 5053 5054 5055 5056 5057 5058 5059
  int insertMode;

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

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

5061
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5062
  char* buffer = calloc(maxSqlLen, 1);
5063
  if (NULL == buffer) {
5064
    errorPrint( "%s() LN%d, Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5065
              __func__, __LINE__, maxSqlLen, strerror(errno));
5066 5067 5068
    return NULL;
  }

5069
  char tableName[TSDB_TABLE_NAME_LEN];
5070 5071 5072 5073

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

5074
  int64_t nTimeStampStep = superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
5075

5076
  uint64_t insert_interval =
5077
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5078 5079
  uint64_t st = 0;
  uint64_t et = UINT64_MAX;
5080

5081 5082 5083
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5084

5085
  uint64_t tableSeq = pThreadInfo->start_table_from;
5086

5087
  debugPrint("[%d] %s() LN%d: start_table_from=%"PRIu64" ntables=%"PRIu64" insertRows=%"PRIu64"\n",
5088 5089
          pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->start_table_from,
          pThreadInfo->ntables, insertRows);
5090 5091 5092

  int64_t startTime = pThreadInfo->start_time;

5093 5094
  assert(pThreadInfo->ntables > 0);

5095 5096
  uint64_t batchPerTbl = interlaceRows;
  uint64_t batchPerTblTimes;
5097

5098
  if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
5099
    batchPerTblTimes =
5100
        g_args.num_of_RPR / interlaceRows;
5101 5102 5103 5104
  } else {
    batchPerTblTimes = 1;
  }

5105
  uint64_t generatedRecPerTbl = 0;
5106
  bool flagSleep = true;
5107
  uint64_t sleepTimeTotal = 0;
5108

5109 5110 5111
  char *strInsertInto = "insert into ";
  int nInsertBufLen = strlen(strInsertInto);

5112
  while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) {
5113
    if ((flagSleep) && (insert_interval)) {
5114 5115
        st = taosGetTimestampMs();
        flagSleep = false;
5116 5117
    }
    // generate data
5118
    memset(buffer, 0, maxSqlLen);
5119
    uint64_t remainderBufLen = maxSqlLen;
5120

5121
    char *pstr = buffer;
5122 5123 5124 5125 5126

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

5127
    uint64_t recOfBatch = 0;
5128

5129
    for (uint64_t i = 0; i < batchPerTblTimes; i ++) {
5130
      getTableName(tableName, pThreadInfo, tableSeq);
5131 5132
      if (0 == strlen(tableName)) {
        errorPrint("[%d] %s() LN%d, getTableName return null\n",
5133
            pThreadInfo->threadID, __func__, __LINE__);
5134
        free(buffer);
5135 5136
        return NULL;
      }
5137

5138
      uint64_t oldRemainderLen = remainderBufLen;
5139
      int64_t generated = generateInterlaceDataBuffer(
5140 5141 5142 5143 5144 5145
        tableName, batchPerTbl, i, batchPerTblTimes,
        tableSeq,
        pThreadInfo, pstr,
        insertRows,
        startTime,
        &remainderBufLen);
5146

5147 5148
      debugPrint("[%d] %s() LN%d, generated records is %"PRId64"\n",
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5149
      if (generated < 0) {
5150
        errorPrint("[%d] %s() LN%d, generated records is %"PRId64"\n",
5151
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5152
        goto free_of_interlace;
5153 5154
      } else if (generated == 0) {
        break;
5155 5156
      }

5157
      tableSeq ++;
5158
      recOfBatch += batchPerTbl;
5159
      pstr += (oldRemainderLen - remainderBufLen);
5160
//      startTime += batchPerTbl * superTblInfo->timeStampStep;
5161
      pThreadInfo->totalInsertRows += batchPerTbl;
5162
      verbosePrint("[%d] %s() LN%d batchPerTbl=%"PRId64" recOfBatch=%"PRId64"\n",
5163 5164
                pThreadInfo->threadID, __func__, __LINE__,
                batchPerTbl, recOfBatch);
5165

5166
      if (insertMode == INTERLACE_INSERT_MODE) {
5167 5168 5169 5170
          if (tableSeq == pThreadInfo->start_table_from + pThreadInfo->ntables) {
            // turn to first table
            tableSeq = pThreadInfo->start_table_from;
            generatedRecPerTbl += batchPerTbl;
5171

5172 5173
            startTime = pThreadInfo->start_time
              + generatedRecPerTbl * nTimeStampStep;
5174

5175 5176 5177
            flagSleep = true;
            if (generatedRecPerTbl >= insertRows)
              break;
5178

5179 5180 5181
            int remainRows = insertRows - generatedRecPerTbl;
            if ((remainRows > 0) && (batchPerTbl > remainRows))
              batchPerTbl = remainRows;
5182

5183 5184 5185 5186
            if (pThreadInfo->ntables * batchPerTbl < g_args.num_of_RPR)
                break;
          }
      }
5187

5188
      verbosePrint("[%d] %s() LN%d generatedRecPerTbl=%"PRId64" insertRows=%"PRId64"\n",
5189 5190
                pThreadInfo->threadID, __func__, __LINE__,
                generatedRecPerTbl, insertRows);
5191 5192

      if ((g_args.num_of_RPR - recOfBatch) < batchPerTbl)
5193 5194 5195
        break;
    }

5196
    verbosePrint("[%d] %s() LN%d recOfBatch=%"PRIu64" totalInsertRows=%"PRIu64"\n",
5197 5198
              pThreadInfo->threadID, __func__, __LINE__, recOfBatch,
              pThreadInfo->totalInsertRows);
5199
    verbosePrint("[%d] %s() LN%d, buffer=%s\n",
5200
           pThreadInfo->threadID, __func__, __LINE__, buffer);
5201

5202
    startTs = taosGetTimestampMs();
5203

5204 5205 5206 5207 5208 5209 5210
    if (recOfBatch == 0) {
      errorPrint("[%d] %s() LN%d try inserting records of batch is %"PRIu64"\n",
              pThreadInfo->threadID, __func__, __LINE__,
              recOfBatch);
      errorPrint("%s\n", "\tPlease check if the batch or the buffer length is proper value!\n");
      goto free_of_interlace;
    }
5211
    int64_t affectedRows = execInsert(pThreadInfo, buffer, recOfBatch);
5212

5213
    endTs = taosGetTimestampMs();
5214 5215
    uint64_t delay = endTs - startTs;
    performancePrint("%s() LN%d, insert execution time is %"PRIu64"ms\n",
5216
            __func__, __LINE__, delay);
5217 5218 5219
    verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5220 5221 5222 5223 5224 5225

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

5226 5227
    if (recOfBatch != affectedRows) {
        errorPrint("[%d] %s() LN%d execInsert insert %"PRIu64", affected rows: %"PRId64"\n%s\n",
5228 5229
                pThreadInfo->threadID, __func__, __LINE__,
                recOfBatch, affectedRows, buffer);
5230
        goto free_of_interlace;
5231
    }
5232

5233
    pThreadInfo->totalAffectedRows += affectedRows;
5234

5235 5236
    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
5237
      printf("thread[%d] has currently inserted rows: %"PRIu64 ", affected rows: %"PRIu64 "\n",
5238 5239 5240
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5241 5242
      lastPrintTime = currentPrintTime;
    }
5243

5244
    if ((insert_interval) && flagSleep) {
5245
      et = taosGetTimestampMs();
5246

5247 5248
      if (insert_interval > (et - st) ) {
        int sleepTime = insert_interval - (et -st);
5249
        performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
5250
                    __func__, __LINE__, sleepTime);
5251 5252 5253
        taosMsleep(sleepTime); // ms
        sleepTimeTotal += insert_interval;
      }
5254
    }
5255 5256
  }

5257
free_of_interlace:
5258
  tmfree(buffer);
5259
  printStatPerThread(pThreadInfo);
5260 5261 5262
  return NULL;
}

5263 5264 5265 5266 5267 5268 5269 5270
// 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
*/
5271
static void* syncWriteProgressive(threadInfo *pThreadInfo) {
5272
  debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__);
5273

5274
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5275
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5276

5277
  char* buffer = calloc(maxSqlLen, 1);
5278
  if (NULL == buffer) {
5279
    errorPrint( "Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5280 5281
              maxSqlLen,
              strerror(errno));
5282 5283
    return NULL;
  }
5284

5285 5286 5287
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5288

5289
  int64_t timeStampStep =
5290
      superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
5291
/*  int insert_interval =
5292
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5293 5294
  uint64_t st = 0;
  uint64_t et = 0xffffffff;
5295
  */
5296

5297 5298
  pThreadInfo->totalInsertRows = 0;
  pThreadInfo->totalAffectedRows = 0;
5299

5300
  pThreadInfo->samplePos = 0;
5301

5302
  for (uint64_t tableSeq =
5303 5304
          pThreadInfo->start_table_from; tableSeq <= pThreadInfo->end_table_to;
        tableSeq ++) {
5305
    int64_t start_time = pThreadInfo->start_time;
5306

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

5310
    for (uint64_t i = 0; i < insertRows;) {
5311 5312 5313 5314 5315
        /*
      if (insert_interval) {
            st = taosGetTimestampMs();
      }
      */
5316

5317 5318
      char tableName[TSDB_TABLE_NAME_LEN];
      getTableName(tableName, pThreadInfo, tableSeq);
5319
      verbosePrint("%s() LN%d: tid=%d seq=%"PRId64" tableName=%s\n",
5320 5321
             __func__, __LINE__,
             pThreadInfo->threadID, tableSeq, tableName);
5322

5323
      int64_t remainderBufLen = maxSqlLen;
5324 5325 5326 5327 5328 5329 5330 5331
      char *pstr = buffer;
      int nInsertBufLen = strlen("insert into ");

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

      pstr += len;
      remainderBufLen -= len;

5332
      int64_t generated = generateProgressiveDataBuffer(
5333 5334 5335 5336
              tableName, tableSeq, pThreadInfo, pstr, insertRows,
            i, start_time,
            &(pThreadInfo->samplePos),
            &remainderBufLen);
5337 5338 5339
      if (generated > 0)
        i += generated;
      else
5340
        goto free_of_progressive;
5341

5342
      start_time +=  generated * timeStampStep;
5343
      pThreadInfo->totalInsertRows += generated;
5344

5345
      startTs = taosGetTimestampMs();
5346

5347
      int64_t affectedRows = execInsert(pThreadInfo, buffer, generated);
5348

5349
      endTs = taosGetTimestampMs();
5350
      uint64_t delay = endTs - startTs;
5351
      performancePrint("%s() LN%d, insert execution time is %"PRId64"ms\n",
5352
              __func__, __LINE__, delay);
5353 5354 5355
      verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5356

5357 5358 5359 5360
      if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
      if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
      pThreadInfo->cntDelay++;
      pThreadInfo->totalDelay += delay;
5361

5362 5363 5364 5365 5366
      if (affectedRows < 0) {
        errorPrint("%s() LN%d, affected rows: %"PRId64"\n",
                __func__, __LINE__, affectedRows);
        goto free_of_progressive;
      }
5367 5368 5369

      pThreadInfo->totalAffectedRows += affectedRows;

5370 5371
      int64_t  currentPrintTime = taosGetTimestampMs();
      if (currentPrintTime - lastPrintTime > 30*1000) {
5372
        printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
5373 5374 5375
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5376 5377 5378
        lastPrintTime = currentPrintTime;
      }

5379
      if (i >= insertRows)
5380
        break;
5381
/*
5382
      if (insert_interval) {
5383
        et = taosGetTimestampMs();
5384

5385 5386
        if (insert_interval > ((et - st)) ) {
            int sleep_time = insert_interval - (et -st);
5387 5388
            performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
                    __func__, __LINE__, sleep_time);
5389 5390
            taosMsleep(sleep_time); // ms
        }
5391
      }
5392
      */
5393 5394
    }   // num_of_DPT

5395 5396
    if (g_args.verbose_print) {
      if ((tableSeq == pThreadInfo->ntables - 1) && superTblInfo &&
5397 5398
        (0 == strncasecmp(
                    superTblInfo->dataSource, "sample", strlen("sample")))) {
5399
          verbosePrint("%s() LN%d samplePos=%"PRId64"\n",
5400
                  __func__, __LINE__, pThreadInfo->samplePos);
5401
      }
5402
    }
5403
  } // tableSeq
5404

5405
free_of_progressive:
5406
  tmfree(buffer);
5407
  printStatPerThread(pThreadInfo);
5408
  return NULL;
H
Hui Li 已提交
5409 5410
}

5411 5412
static void* syncWrite(void *sarg) {

5413 5414
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5415

5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427
  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;
  }
5428

5429
  if (interlaceRows > 0) {
5430
    // interlace mode
5431
    return syncWriteInterlace(pThreadInfo);
5432 5433
  } else {
    // progressive mode
5434
    return syncWriteProgressive(pThreadInfo);
5435
  }
5436

5437 5438
}

5439
static void callBack(void *param, TAOS_RES *res, int code) {
5440 5441
  threadInfo* pThreadInfo = (threadInfo*)param;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5442

5443 5444
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5445
  if (insert_interval) {
5446 5447 5448
    pThreadInfo->et = taosGetTimestampMs();
    if ((pThreadInfo->et - pThreadInfo->st) < insert_interval) {
      taosMsleep(insert_interval - (pThreadInfo->et - pThreadInfo->st)); // ms
5449
    }
H
Hui Li 已提交
5450
  }
5451

5452
  char *buffer = calloc(1, pThreadInfo->superTblInfo->maxSqlLen);
5453
  char data[MAX_DATA_SIZE];
5454
  char *pstr = buffer;
5455 5456
  pstr += sprintf(pstr, "insert into %s.%s%"PRId64" values",
          pThreadInfo->db_name, pThreadInfo->tb_prefix,
5457
          pThreadInfo->start_table_from);
5458 5459 5460 5461 5462 5463 5464
//  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);
5465 5466 5467 5468
    free(buffer);
    taos_free_result(res);
    return;
  }
5469

5470
  for (int i = 0; i < g_args.num_of_RPR; i++) {
5471
    int rand_num = taosRandom() % 100;
5472
    if (0 != pThreadInfo->superTblInfo->disorderRatio
5473
            && rand_num < pThreadInfo->superTblInfo->disorderRatio) {
5474 5475
      int64_t d = pThreadInfo->lastTs - (taosRandom() % pThreadInfo->superTblInfo->disorderRange + 1);
      generateRowData(data, d, pThreadInfo->superTblInfo);
5476
    } else {
5477
      generateRowData(data, pThreadInfo->lastTs += 1000, pThreadInfo->superTblInfo);
H
Hui Li 已提交
5478
    }
5479
    pstr += sprintf(pstr, "%s", data);
5480
    pThreadInfo->counter++;
H
Hui Li 已提交
5481

5482
    if (pThreadInfo->counter >= pThreadInfo->superTblInfo->insertRows) {
5483
      break;
H
Hui Li 已提交
5484 5485
    }
  }
5486

5487
  if (insert_interval) {
5488
    pThreadInfo->st = taosGetTimestampMs();
5489
  }
5490
  taos_query_a(pThreadInfo->taos, buffer, callBack, pThreadInfo);
5491
  free(buffer);
H
Hui Li 已提交
5492

5493
  taos_free_result(res);
H
Hui Li 已提交
5494 5495
}

5496
static void *asyncWrite(void *sarg) {
5497 5498
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5499

5500 5501 5502
  pThreadInfo->st = 0;
  pThreadInfo->et = 0;
  pThreadInfo->lastTs = pThreadInfo->start_time;
5503

5504
  int insert_interval =
5505
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5506
  if (insert_interval) {
5507
    pThreadInfo->st = taosGetTimestampMs();
H
Hui Li 已提交
5508
  }
5509
  taos_query_a(pThreadInfo->taos, "show databases", callBack, pThreadInfo);
5510

5511
  tsem_wait(&(pThreadInfo->lock_sem));
H
Hui Li 已提交
5512 5513 5514 5515

  return NULL;
}

5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541
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;
}

5542
static void startMultiThreadInsertData(int threads, char* db_name,
5543
        char* precision,SSuperTable* superTblInfo) {
5544

5545 5546
  pthread_t *pids = malloc(threads * sizeof(pthread_t));
  assert(pids != NULL);
H
Hui Li 已提交
5547

5548 5549
  threadInfo *infos = malloc(threads * sizeof(threadInfo));
  assert(infos != NULL);
5550

5551 5552
  memset(pids, 0, threads * sizeof(pthread_t));
  memset(infos, 0, threads * sizeof(threadInfo));
5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569

  //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 {
5570
      errorPrint("Not support precision: %s\n", precision);
5571 5572 5573 5574
      exit(-1);
    }
  }

5575
  int64_t start_time;
5576 5577
  if (superTblInfo) {
    if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
5578
        start_time = taosGetTimestamp(timePrec);
5579
    } else {
5580
      if (TSDB_CODE_SUCCESS != taosParseTime(
5581 5582 5583 5584 5585
        superTblInfo->startTimestamp,
        &start_time,
        strlen(superTblInfo->startTimestamp),
        timePrec, 0)) {
          ERROR_EXIT("failed to parse time!\n");
5586
      }
5587
    }
5588
  } else {
5589
     start_time = 1500000000000;
5590 5591
  }

5592
  int64_t start = taosGetTimestampMs();
5593

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

5604
  // read sample data from file first
5605
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5606
              "sample", strlen("sample")))) {
5607
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5608
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
5609
              __func__, __LINE__);
5610 5611 5612 5613 5614
      exit(-1);
    }
  }

  TAOS* taos = taos_connect(
5615 5616
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
5617
  if (NULL == taos) {
5618
    errorPrint("%s() LN%d, connect to server fail , reason: %s\n",
5619
                __func__, __LINE__, taos_errstr(NULL));
5620 5621 5622
    exit(-1);
  }

5623 5624
  int ntables = 0;
  int startFrom;
5625

5626
  if (superTblInfo) {
5627 5628
    int64_t limit;
    uint64_t offset;
5629

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

5635
    if (superTblInfo->childTblExists == TBL_ALREADY_EXISTS) {
5636 5637
      if ((superTblInfo->childTblLimit < 0)
          || ((superTblInfo->childTblOffset + superTblInfo->childTblLimit)
5638
            > (superTblInfo->childTblCount))) {
5639 5640 5641 5642 5643 5644
        superTblInfo->childTblLimit =
            superTblInfo->childTblCount - superTblInfo->childTblOffset;
      }

      offset = superTblInfo->childTblOffset;
      limit = superTblInfo->childTblLimit;
5645
    } else {
5646 5647
      limit = superTblInfo->childTblCount;
      offset = 0;
5648 5649
    }

5650 5651 5652
    ntables = limit;
    startFrom = offset;

5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663
    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)
5664
            && (0 == superTblInfo->childTblLimit)) {
5665 5666 5667 5668 5669 5670 5671
      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();
      }
    }

5672
    superTblInfo->childTblName = (char*)calloc(1,
5673
        limit * TSDB_TABLE_NAME_LEN);
5674
    if (superTblInfo->childTblName == NULL) {
5675
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
5676 5677 5678 5679
      taos_close(taos);
      exit(-1);
    }

5680
    uint64_t childTblCount;
5681 5682 5683 5684 5685 5686
    getChildNameOfSuperTableWithLimitAndOffset(
        taos,
        db_name, superTblInfo->sTblName,
        &superTblInfo->childTblName, &childTblCount,
        limit,
        offset);
5687 5688 5689
  } else {
    ntables = g_args.num_of_tables;
    startFrom = 0;
5690
  }
5691

5692 5693
  taos_close(taos);

5694
  uint64_t a = ntables / threads;
5695 5696 5697 5698 5699
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

5700
  uint64_t b = 0;
5701 5702 5703 5704
  if (threads != 0) {
    b = ntables % threads;
  }

5705 5706 5707 5708 5709 5710
  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 已提交
5711
  for (int i = 0; i < threads; i++) {
5712
    threadInfo *t_info = infos + i;
H
Hui Li 已提交
5713 5714
    t_info->threadID = i;
    tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE);
5715
    t_info->time_precision = timePrec;
5716 5717 5718
    t_info->superTblInfo = superTblInfo;

    t_info->start_time = start_time;
5719
    t_info->minDelay = UINT64_MAX;
5720

5721
    if ((NULL == superTblInfo) ||
5722
            (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5))) {
5723
      //t_info->taos = taos;
5724
      t_info->taos = taos_connect(
5725 5726
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
5727
      if (NULL == t_info->taos) {
5728
        errorPrint(
5729 5730
                "connect to server fail from insert sub thread, reason: %s\n",
                taos_errstr(NULL));
5731 5732 5733 5734 5735 5736
        exit(-1);
      }
    } else {
      t_info->taos = NULL;
    }

5737
/*    if ((NULL == superTblInfo)
5738
            || (0 == superTblInfo->multiThreadWriteOneTbl)) {
5739
            */
5740 5741 5742 5743
      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;
5744
/*    } else {
5745 5746
      t_info->start_table_from = 0;
      t_info->ntables = superTblInfo->childTblCount;
5747 5748
      t_info->start_time = t_info->start_time + rand_int() % 10000 - rand_tinyint();
    }
5749
*/
5750 5751
    tsem_init(&(t_info->lock_sem), 0, 0);
    if (SYNC == g_Dbs.queryMode) {
5752
      pthread_create(pids + i, NULL, syncWrite, t_info);
5753
    } else {
5754 5755
      pthread_create(pids + i, NULL, asyncWrite, t_info);
    }
H
Hui Li 已提交
5756
  }
5757

H
Hui Li 已提交
5758 5759 5760 5761
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

5762 5763 5764 5765
  uint64_t totalDelay = 0;
  uint64_t maxDelay = 0;
  uint64_t minDelay = UINT64_MAX;
  uint64_t cntDelay = 1;
5766 5767
  double  avgDelay = 0;

H
Hui Li 已提交
5768
  for (int i = 0; i < threads; i++) {
5769 5770
    threadInfo *t_info = infos + i;

S
TD-1057  
Shengliang Guan 已提交
5771
    tsem_destroy(&(t_info->lock_sem));
5772 5773
    taos_close(t_info->taos);

5774
    debugPrint("%s() LN%d, [%d] totalInsert=%"PRIu64" totalAffected=%"PRIu64"\n",
5775 5776 5777
            __func__, __LINE__,
            t_info->threadID, t_info->totalInsertRows,
            t_info->totalAffectedRows);
5778
    if (superTblInfo) {
5779 5780
        superTblInfo->totalAffectedRows += t_info->totalAffectedRows;
        superTblInfo->totalInsertRows += t_info->totalInsertRows;
5781
    } else {
5782 5783
        g_args.totalAffectedRows += t_info->totalAffectedRows;
        g_args.totalInsertRows += t_info->totalInsertRows;
5784
    }
5785 5786 5787 5788

    totalDelay  += t_info->totalDelay;
    cntDelay   += t_info->cntDelay;
    if (t_info->maxDelay > maxDelay) maxDelay = t_info->maxDelay;
5789
    if (t_info->minDelay < minDelay) minDelay = t_info->minDelay;
H
Hui Li 已提交
5790
  }
5791
  cntDelay -= 1;
H
Hui Li 已提交
5792

5793
  if (cntDelay == 0)    cntDelay = 1;
5794 5795
  avgDelay = (double)totalDelay / cntDelay;

5796 5797
  int64_t end = taosGetTimestampMs();
  int64_t t = end - start;
5798 5799

  if (superTblInfo) {
5800
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
5801 5802 5803 5804
          t / 1000.0, superTblInfo->totalInsertRows,
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
5805 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.%s. %.2f records/second\n\n",
5809 5810 5811 5812
          t / 1000.0, superTblInfo->totalInsertRows,
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
5813
    }
5814
  } else {
5815
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n",
5816 5817 5818 5819
          t / 1000.0, g_args.totalInsertRows,
          g_args.totalAffectedRows,
          threads, db_name,
          (double)g_args.totalInsertRows / (t / 1000.0));
5820 5821 5822
    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",
5823 5824 5825 5826
          t * 1000.0, g_args.totalInsertRows,
          g_args.totalAffectedRows,
          threads, db_name,
          (double)g_args.totalInsertRows / (t / 1000.0));
5827
    }
5828
  }
5829

5830
  fprintf(stderr, "insert delay, avg: %10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
5831
          avgDelay, maxDelay, minDelay);
5832 5833
  if (g_fpOfInsertResult) {
    fprintf(g_fpOfInsertResult, "insert delay, avg:%10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
5834
          avgDelay, maxDelay, minDelay);
5835
  }
5836

5837 5838
  //taos_close(taos);

H
Hui Li 已提交
5839
  free(pids);
5840
  free(infos);
H
Hui Li 已提交
5841 5842
}

5843
static void *readTable(void *sarg) {
5844
#if 1
5845
  threadInfo *rinfo = (threadInfo *)sarg;
H
hzcheng 已提交
5846 5847
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
5848
  uint64_t sTime = rinfo->start_time;
H
hzcheng 已提交
5849 5850
  char *tb_prefix = rinfo->tb_prefix;
  FILE *fp = fopen(rinfo->fp, "a");
H
Hui Li 已提交
5851
  if (NULL == fp) {
5852
    errorPrint( "fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno));
H
Hui Li 已提交
5853 5854
    return NULL;
  }
5855

5856
    int num_of_DPT;
5857
/*  if (rinfo->superTblInfo) {
5858 5859
    num_of_DPT = rinfo->superTblInfo->insertRows; //  nrecords_per_table;
  } else {
5860
  */
5861
      num_of_DPT = g_args.num_of_DPT;
5862
//  }
5863

5864
  int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
H
hzcheng 已提交
5865
  int totalData = num_of_DPT * num_of_tables;
5866
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5867 5868 5869 5870 5871 5872 5873 5874

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

5875
  for (uint64_t j = 0; j < n; j++) {
H
hzcheng 已提交
5876
    double totalT = 0;
5877 5878 5879
    uint64_t count = 0;
    for (uint64_t i = 0; i < num_of_tables; i++) {
      sprintf(command, "select %s from %s%"PRIu64" where ts>= %" PRIu64,
5880
              aggreFunc[j], tb_prefix, i, sTime);
H
hzcheng 已提交
5881

5882
      double t = taosGetTimestampMs();
S
Shuaiqiang Chang 已提交
5883 5884
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);
H
hzcheng 已提交
5885

S
Shuaiqiang Chang 已提交
5886
      if (code != 0) {
5887
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
5888
        taos_free_result(pSql);
H
hzcheng 已提交
5889
        taos_close(taos);
5890
        fclose(fp);
5891
        return NULL;
H
hzcheng 已提交
5892 5893
      }

5894
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
5895 5896 5897
        count++;
      }

5898
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
5899 5900
      totalT += t;

S
Shuaiqiang Chang 已提交
5901
      taos_free_result(pSql);
H
hzcheng 已提交
5902 5903 5904
    }

    fprintf(fp, "|%10s  |   %10d   |  %12.2f   |   %10.2f  |\n",
S
slguan 已提交
5905
            aggreFunc[j][0] == '*' ? "   *   " : aggreFunc[j], totalData,
H
hzcheng 已提交
5906
            (double)(num_of_tables * num_of_DPT) / totalT, totalT * 1000);
5907
    printf("select %10s took %.6f second(s)\n", aggreFunc[j], totalT * 1000);
H
hzcheng 已提交
5908 5909 5910
  }
  fprintf(fp, "\n");
  fclose(fp);
5911
#endif
H
hzcheng 已提交
5912 5913 5914
  return NULL;
}

5915
static void *readMetric(void *sarg) {
5916
#if 1
5917
  threadInfo *rinfo = (threadInfo *)sarg;
H
hzcheng 已提交
5918 5919 5920
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
  FILE *fp = fopen(rinfo->fp, "a");
H
Hui Li 已提交
5921 5922 5923 5924
  if (NULL == fp) {
    printf("fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno));
    return NULL;
  }
5925 5926

  int num_of_DPT = rinfo->superTblInfo->insertRows;
5927
  int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
H
hzcheng 已提交
5928
  int totalData = num_of_DPT * num_of_tables;
5929
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5930 5931 5932 5933 5934 5935 5936 5937 5938

  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 已提交
5939
    char condition[BUFFER_SIZE - 30] = "\0";
B
Bomin Zhang 已提交
5940
    char tempS[64] = "\0";
H
hzcheng 已提交
5941 5942 5943 5944 5945

    int m = 10 < num_of_tables ? 10 : num_of_tables;

    for (int i = 1; i <= m; i++) {
      if (i == 1) {
5946
        sprintf(tempS, "t1 = %d", i);
H
hzcheng 已提交
5947
      } else {
5948
        sprintf(tempS, " or t1 = %d ", i);
H
hzcheng 已提交
5949 5950 5951
      }
      strcat(condition, tempS);

L
liu0x54 已提交
5952
      sprintf(command, "select %s from meters where %s", aggreFunc[j], condition);
H
hzcheng 已提交
5953 5954 5955 5956

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

5957
      double t = taosGetTimestampMs();
H
hzcheng 已提交
5958

S
Shuaiqiang Chang 已提交
5959 5960 5961 5962
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);

      if (code != 0) {
5963
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
5964
        taos_free_result(pSql);
H
hzcheng 已提交
5965
        taos_close(taos);
5966
        fclose(fp);
5967
        return NULL;
H
hzcheng 已提交
5968 5969
      }
      int count = 0;
5970
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
5971 5972
        count++;
      }
5973
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
5974

5975
      fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n",
5976 5977
              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 已提交
5978

S
Shuaiqiang Chang 已提交
5979
      taos_free_result(pSql);
H
hzcheng 已提交
5980 5981 5982 5983
    }
    fprintf(fp, "\n");
  }
  fclose(fp);
5984
#endif
H
hzcheng 已提交
5985 5986 5987
  return NULL;
}

H
Hui Li 已提交
5988

5989
static int insertTestProcess() {
5990

5991 5992 5993
  setupForAnsiEscape();
  int ret = printfInsertMeta();
  resetAfterAnsiEscape();
5994

5995 5996 5997
  if (ret == -1)
    exit(EXIT_FAILURE);

5998
  debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile);
5999 6000
  g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a");
  if (NULL == g_fpOfInsertResult) {
6001
    errorPrint( "Failed to open %s for save result\n", g_Dbs.resultFile);
6002 6003
    return -1;
  }
6004

6005 6006
  if (g_fpOfInsertResult)
    printfInsertMetaToFile(g_fpOfInsertResult);
6007

6008 6009 6010 6011
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
6012

6013 6014 6015
  init_rand_data();

  // create database and super tables
6016
  if(createDatabasesAndStables() != 0) {
6017 6018
    if (g_fpOfInsertResult)
      fclose(g_fpOfInsertResult);
6019 6020
    return -1;
  }
6021 6022

  // pretreatement
6023
  prepareSampleData();
6024

6025 6026 6027 6028
  double start;
  double end;

  // create child tables
6029
  start = taosGetTimestampMs();
6030
  createChildTables();
6031
  end = taosGetTimestampMs();
6032

6033
  if (g_totalChildTables > 0) {
6034
    fprintf(stderr, "Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
6035
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6036 6037
    if (g_fpOfInsertResult) {
      fprintf(g_fpOfInsertResult,
6038
            "Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
6039
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6040
    }
6041
  }
6042

6043
  taosMsleep(1000);
6044
  // create sub threads for inserting data
6045
  //start = taosGetTimestampMs();
6046
  for (int i = 0; i < g_Dbs.dbCount; i++) {
6047 6048 6049 6050 6051 6052 6053 6054
    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(
6055 6056 6057 6058
              g_Dbs.threadCount,
              g_Dbs.db[i].dbName,
              g_Dbs.db[i].dbCfg.precision,
              superTblInfo);
6059
          }
6060
        }
6061
      }
6062
    } else {
6063
        startMultiThreadInsertData(
6064 6065 6066
          g_Dbs.threadCount,
          g_Dbs.db[i].dbName,
          g_Dbs.db[i].dbCfg.precision,
6067
          NULL);
H
Hui Li 已提交
6068
    }
6069
  }
6070
  //end = taosGetTimestampMs();
6071

6072
  //int64_t    totalInsertRows = 0;
6073
  //int64_t    totalAffectedRows = 0;
6074
  //for (int i = 0; i < g_Dbs.dbCount; i++) {
6075
  //  for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
6076
  //  totalInsertRows+= g_Dbs.db[i].superTbls[j].totalInsertRows;
6077 6078
  //  totalAffectedRows += g_Dbs.db[i].superTbls[j].totalAffectedRows;
  //}
6079
  //printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s)\n\n", end - start, totalInsertRows, totalAffectedRows, g_Dbs.threadCount);
6080
  postFreeResource();
6081

6082 6083 6084
  return 0;
}

6085 6086
static void *specifiedTableQuery(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6087

6088
  if (pThreadInfo->taos == NULL) {
6089 6090
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
6091 6092 6093 6094
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
          g_queryInfo.port);
6095 6096
    if (taos == NULL) {
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6097
            pThreadInfo->threadID, taos_errstr(NULL));
6098 6099
      return NULL;
    } else {
6100
      pThreadInfo->taos = taos;
6101 6102 6103
    }
  }

6104 6105
  char sqlStr[MAX_DB_NAME_SIZE + 5];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6106 6107
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6108 6109 6110 6111
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
    return NULL;
  }
6112

6113 6114
  uint64_t st = 0;
  uint64_t et = 0;
6115

6116
  uint64_t queryTimes = g_queryInfo.specifiedQueryInfo.queryTimes;
6117

6118 6119 6120
  uint64_t totalQueried = 0;
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
6121

6122
  while(queryTimes --) {
6123
    if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) <
6124
            (int64_t)g_queryInfo.specifiedQueryInfo.queryInterval) {
6125
      taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval - (et - st)); // ms
6126 6127
    }

6128
    st = taosGetTimestampMs();
6129

6130
    if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", strlen("taosc"))) {
6131
      int64_t t1 = taosGetTimestampMs();
6132
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6133
      if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
6134
        sprintf(tmpFile, "%s-%d",
6135 6136
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
6137
      }
6138
      selectAndGetResult(pThreadInfo->taos,
6139
          g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq], tmpFile);
6140 6141
      int64_t t2 = taosGetTimestampMs();
      printf("=[taosc] thread[%"PRId64"] complete one sql, Spent %10.3f s\n",
6142
              taosGetSelfPthreadId(), (t2 - t1)/1000.0);
6143
    } else if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
6144
      int64_t t1 = taosGetTimestampMs();
6145
      int retCode = postProceSql(g_queryInfo.host, &(g_queryInfo.serv_addr),
6146 6147
              g_queryInfo.port,
              g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq]);
6148 6149 6150 6151
      if (0 != retCode) {
        printf("====restful return fail, threadID[%d]\n", pThreadInfo->threadID);
        return NULL;
      }
6152 6153 6154
      int64_t t2 = taosGetTimestampMs();
      printf("=[restful] thread[%"PRId64"] complete one sql, Spent %10.3f s\n",
              taosGetSelfPthreadId(), (t2 - t1)/1000.0);
6155

6156 6157 6158 6159
    } else {
      errorPrint("%s() LN%d, unknown query mode: %s\n",
        __func__, __LINE__, g_queryInfo.queryMode);
      return NULL;
6160
    }
6161 6162
    totalQueried ++;
    g_queryInfo.specifiedQueryInfo.totalQueried ++;
6163

6164
    et = taosGetTimestampMs();
6165

6166 6167
    uint64_t  currentPrintTime = taosGetTimestampMs();
    uint64_t  endTs = taosGetTimestampMs();
6168
    if (currentPrintTime - lastPrintTime > 30*1000) {
6169
      debugPrint("%s() LN%d, endTs=%"PRIu64"ms, startTs=%"PRIu64"ms\n",
6170
          __func__, __LINE__, endTs, startTs);
6171
      printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.6f\n",
6172 6173
                    pThreadInfo->threadID,
                    totalQueried,
6174
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6175
      lastPrintTime = currentPrintTime;
6176
    }
H
Hui Li 已提交
6177
  }
6178 6179
  return NULL;
}
H
Hui Li 已提交
6180

6181
static void replaceChildTblName(char* inSql, char* outSql, int tblIndex) {
6182 6183
  char sourceString[32] = "xxxx";
  char subTblName[MAX_TB_NAME_SIZE*3];
6184 6185
  sprintf(subTblName, "%s.%s",
          g_queryInfo.dbName,
6186
          g_queryInfo.superQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN);
6187 6188

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

6190 6191
  char* pos = strstr(inSql, sourceString);
  if (0 == pos) {
6192
    return;
H
Hui Li 已提交
6193
  }
6194

6195
  tstrncpy(outSql, inSql, pos - inSql + 1);
6196
  //printf("1: %s\n", outSql);
6197 6198 6199 6200
  strcat(outSql, subTblName);
  //printf("2: %s\n", outSql);
  strcat(outSql, pos+strlen(sourceString));
  //printf("3: %s\n", outSql);
H
Hui Li 已提交
6201 6202
}

6203
static void *superTableQuery(void *sarg) {
6204
  char sqlstr[1024];
6205
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6206

6207
  if (pThreadInfo->taos == NULL) {
6208 6209 6210 6211 6212 6213 6214 6215
    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",
6216
            pThreadInfo->threadID, taos_errstr(NULL));
6217 6218
      return NULL;
    } else {
6219
      pThreadInfo->taos = taos;
6220 6221 6222
    }
  }

6223 6224
  uint64_t st = 0;
  uint64_t et = (int64_t)g_queryInfo.superQueryInfo.queryInterval;
6225

6226 6227 6228
  uint64_t queryTimes = g_queryInfo.superQueryInfo.queryTimes;
  uint64_t totalQueried = 0;
  uint64_t  startTs = taosGetTimestampMs();
6229

6230
  uint64_t  lastPrintTime = taosGetTimestampMs();
6231
  while(queryTimes --) {
6232 6233 6234
    if (g_queryInfo.superQueryInfo.queryInterval
            && (et - st) < (int64_t)g_queryInfo.superQueryInfo.queryInterval) {
      taosMsleep(g_queryInfo.superQueryInfo.queryInterval - (et - st)); // ms
6235
      //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6236
    }
H
Hui Li 已提交
6237

6238
    st = taosGetTimestampMs();
6239
    for (int i = pThreadInfo->start_table_from; i <= pThreadInfo->end_table_to; i++) {
6240
      for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
6241
        memset(sqlstr,0,sizeof(sqlstr));
6242
        replaceChildTblName(g_queryInfo.superQueryInfo.sql[j], sqlstr, i);
6243
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6244
        if (g_queryInfo.superQueryInfo.result[j][0] != 0) {
6245
          sprintf(tmpFile, "%s-%d",
6246
                  g_queryInfo.superQueryInfo.result[j],
6247
                  pThreadInfo->threadID);
6248
        }
6249 6250 6251 6252 6253 6254 6255 6256
        selectAndGetResult(pThreadInfo->taos, sqlstr, tmpFile);

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

        int64_t  currentPrintTime = taosGetTimestampMs();
        int64_t  endTs = taosGetTimestampMs();
        if (currentPrintTime - lastPrintTime > 30*1000) {
6257
          printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.3f\n",
6258 6259
                    pThreadInfo->threadID,
                    totalQueried,
6260
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6261
          lastPrintTime = currentPrintTime;
6262
        }
6263
      }
H
Hui Li 已提交
6264
    }
6265
    et = taosGetTimestampMs();
6266
    printf("####thread[%"PRId64"] complete all sqls to allocate all sub-tables[%"PRIu64" - %"PRIu64"] once queries duration:%.4fs\n\n",
6267
            taosGetSelfPthreadId(),
6268 6269
            pThreadInfo->start_table_from,
            pThreadInfo->end_table_to,
6270
            (double)(et - st)/1000.0);
6271
  }
6272

6273 6274 6275
  return NULL;
}

6276
static int queryTestProcess() {
6277 6278 6279 6280

  setupForAnsiEscape();
  printfQueryMeta();
  resetAfterAnsiEscape();
6281 6282 6283 6284 6285 6286

  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
6287
          g_queryInfo.port);
6288
  if (taos == NULL) {
6289 6290
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6291 6292 6293
    exit(-1);
  }

6294
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6295 6296
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6297 6298 6299
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6300
  }
6301

6302 6303 6304 6305
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
6306

6307
  printfQuerySystemInfo(taos);
6308

6309 6310 6311 6312 6313 6314
  if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
    if (convertHostToServAddr(
        g_queryInfo.host, g_queryInfo.port, &g_queryInfo.serv_addr) != 0)
      exit(-1);
  }

6315 6316 6317
  pthread_t  *pids  = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from specify table
6318 6319
  int nConcurrent = g_queryInfo.specifiedQueryInfo.concurrent;
  int nSqlCount = g_queryInfo.specifiedQueryInfo.sqlCount;
6320

6321
  uint64_t startTs = taosGetTimestampMs();
6322

6323 6324 6325 6326 6327 6328
  if ((nSqlCount > 0) && (nConcurrent > 0)) {

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

    if ((NULL == pids) || (NULL == infos)) {
6329
      taos_close(taos);
6330
      ERROR_EXIT("memory allocation failed for create threads\n");
6331
    }
6332

6333 6334 6335 6336 6337
    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;
6338

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

6341 6342 6343 6344
          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)) {
6345
            taos_close(taos);
6346 6347
            free(infos);
            free(pids);
6348 6349 6350
            errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
            return -1;
6351
          }
6352
        }
6353

6354
        t_info->taos = NULL;// TODO: workaround to use separate taos connection;
6355

6356
        pthread_create(pids + i * nSqlCount + j, NULL, specifiedTableQuery,
6357 6358
            t_info);
      }
6359
    }
6360
  } else {
6361
    g_queryInfo.specifiedQueryInfo.concurrent = 0;
6362
  }
6363

6364 6365
  taos_close(taos);

6366 6367 6368
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
  //==== create sub threads for query from all sub table of the super table
6369 6370 6371 6372
  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));
6373 6374

    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6375 6376
      free(infos);
      free(pids);
6377

6378
      ERROR_EXIT("memory allocation failed for create threads\n");
6379
    }
6380

6381
    uint64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
6382
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6383

6384
    uint64_t a = ntables / threads;
6385 6386 6387 6388
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6389

6390
    uint64_t b = 0;
6391 6392 6393
    if (threads != 0) {
      b = ntables % threads;
    }
6394

6395
    uint64_t startFrom = 0;
6396
    for (int i = 0; i < threads; i++) {
6397 6398
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6399

6400 6401 6402 6403
      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;
6404
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6405
      pthread_create(pidsOfSub + i, NULL, superTableQuery, t_info);
6406 6407
    }

6408
    g_queryInfo.superQueryInfo.threadCnt = threads;
6409
  } else {
6410
    g_queryInfo.superQueryInfo.threadCnt = 0;
6411
  }
6412

6413 6414 6415 6416 6417 6418
  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);
      }
    }
6419
  }
S
Shuaiqiang Chang 已提交
6420

6421
  tmfree((char*)pids);
6422
  tmfree((char*)infos);
6423

6424
  for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6425
    pthread_join(pidsOfSub[i], NULL);
H
hzcheng 已提交
6426
  }
H
Hui Li 已提交
6427

6428
  tmfree((char*)pidsOfSub);
6429
  tmfree((char*)infosOfSub);
6430

6431
//  taos_close(taos);// TODO: workaround to use separate taos connection;
6432
  uint64_t endTs = taosGetTimestampMs();
6433

6434
  uint64_t totalQueried = g_queryInfo.specifiedQueryInfo.totalQueried +
6435 6436
    g_queryInfo.superQueryInfo.totalQueried;

6437
  fprintf(stderr, "==== completed total queries: %"PRIu64", the QPS of all threads: %10.3f====\n",
6438
          totalQueried,
6439
          (double)(totalQueried/((endTs-startTs)/1000.0)));
6440 6441 6442
  return 0;
}

6443
static void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
6444
  if (res == NULL || taos_errno(res) != 0) {
6445 6446
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
6447 6448
    return;
  }
6449

6450
  getResult(res, (char*)param);
6451
  // tao_unscribe() will free result.
H
hzcheng 已提交
6452 6453
}

6454 6455
static TAOS_SUB* subscribeImpl(
        TAOS *taos, char *sql, char* topic, char* resultFileName) {
6456
  TAOS_SUB* tsub = NULL;
H
hzcheng 已提交
6457

6458
  if (ASYNC_QUERY_MODE == g_queryInfo.specifiedQueryInfo.mode) {
6459
    tsub = taos_subscribe(taos,
6460
            g_queryInfo.specifiedQueryInfo.subscribeRestart,
6461
            topic, sql, subscribe_callback, (void*)resultFileName,
6462
            g_queryInfo.specifiedQueryInfo.subscribeInterval);
6463
  } else {
6464
    tsub = taos_subscribe(taos,
6465
            g_queryInfo.specifiedQueryInfo.subscribeRestart,
6466
            topic, sql, NULL, NULL, 0);
6467
  }
6468

6469 6470 6471
  if (tsub == NULL) {
    printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
    return NULL;
6472
  }
6473

6474 6475
  return tsub;
}
H
hzcheng 已提交
6476

6477 6478
static void *superSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6479
  char subSqlstr[1024];
6480
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
H
hzcheng 已提交
6481

6482 6483 6484
  if (g_queryInfo.superQueryInfo.sqlCount == 0)
    return NULL;

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

6501 6502
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6503 6504
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6505 6506
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
6507 6508
    return NULL;
  }
6509

6510 6511 6512
  //int64_t st = 0;
  //int64_t et = 0;
  do {
6513 6514
    //if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) < g_queryInfo.specifiedQueryInfo.queryInterval) {
    //  taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval- (et - st)); // ms
6515
    //  //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6516 6517 6518 6519
    //}

    //st = taosGetTimestampMs();
    char topic[32] = {0};
6520
    for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
6521 6522
      sprintf(topic, "taosdemo-subscribe-%d", i);
      memset(subSqlstr,0,sizeof(subSqlstr));
6523
      replaceChildTblName(g_queryInfo.superQueryInfo.sql[i], subSqlstr, i);
6524
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6525
      if (g_queryInfo.superQueryInfo.result[i][0] != 0) {
6526
        sprintf(tmpFile, "%s-%d",
6527
                g_queryInfo.superQueryInfo.result[i], pThreadInfo->threadID);
6528
      }
6529
      tsub[i] = subscribeImpl(pThreadInfo->taos, subSqlstr, topic, tmpFile);
6530
      if (NULL == tsub[i]) {
6531
        taos_close(pThreadInfo->taos);
6532 6533 6534 6535
        return NULL;
      }
    }
    //et = taosGetTimestampMs();
6536
    //printf("========thread[%"PRIu64"] complete all sqls to super table once queries duration:%.4fs\n", taosGetSelfPthreadId(), (double)(et - st)/1000.0);
6537
  } while(0);
6538 6539 6540

  // start loop to consume result
  TAOS_RES* res = NULL;
6541
  while(1) {
6542
    for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
6543
      if (ASYNC_QUERY_MODE == g_queryInfo.superQueryInfo.mode) {
6544 6545
        continue;
      }
6546

6547
      res = taos_consume(tsub[i]);
6548 6549
      if (res) {
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6550
        if (g_queryInfo.superQueryInfo.result[i][0] != 0) {
6551
          sprintf(tmpFile, "%s-%d",
6552
                  g_queryInfo.superQueryInfo.result[i],
6553
                  pThreadInfo->threadID);
6554 6555
        }
        getResult(res, tmpFile);
H
hzcheng 已提交
6556 6557 6558
      }
    }
  }
6559
  taos_free_result(res);
6560

6561
  for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
6562
    taos_unsubscribe(tsub[i], g_queryInfo.superQueryInfo.subscribeKeepProgress);
6563
  }
6564

6565
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
6566 6567 6568
  return NULL;
}

6569 6570
static void *specifiedSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6571
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
H
hzcheng 已提交
6572

6573 6574 6575
  if (g_queryInfo.specifiedQueryInfo.sqlCount == 0)
    return NULL;

6576
  if (pThreadInfo->taos == NULL) {
6577 6578 6579 6580 6581 6582 6583 6584
    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",
6585
            pThreadInfo->threadID, taos_errstr(NULL));
6586 6587
      return NULL;
    } else {
6588
      pThreadInfo->taos = taos;
6589 6590 6591
    }
  }

6592 6593
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6594
  debugPrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
6595 6596
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6597 6598
    return NULL;
  }
6599

6600 6601 6602
  //int64_t st = 0;
  //int64_t et = 0;
  do {
6603 6604
    //if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) < g_queryInfo.specifiedQueryInfo.queryInterval) {
    //  taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval- (et - st)); // ms
6605
    //  //printf("========sleep duration:%"PRIu64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6606 6607 6608 6609
    //}

    //st = taosGetTimestampMs();
    char topic[32] = {0};
6610
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6611 6612
      sprintf(topic, "taosdemo-subscribe-%d", i);
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6613
      if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) {
6614
        sprintf(tmpFile, "%s-%d",
6615
                g_queryInfo.specifiedQueryInfo.result[i], pThreadInfo->threadID);
6616
      }
6617
      tsub[i] = subscribeImpl(pThreadInfo->taos,
6618
          g_queryInfo.specifiedQueryInfo.sql[i], topic, tmpFile);
6619
      if (NULL == tsub[i]) {
6620
        taos_close(pThreadInfo->taos);
6621 6622 6623 6624
        return NULL;
      }
    }
    //et = taosGetTimestampMs();
6625
    //printf("========thread[%"PRIu64"] complete all sqls to super table once queries duration:%.4fs\n", taosGetSelfPthreadId(), (double)(et - st)/1000.0);
6626
  } while(0);
6627 6628 6629

  // start loop to consume result
  TAOS_RES* res = NULL;
6630
  while(1) {
6631
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6632
      if (ASYNC_QUERY_MODE == g_queryInfo.specifiedQueryInfo.mode) {
6633 6634
        continue;
      }
6635

6636
      res = taos_consume(tsub[i]);
6637 6638
      if (res) {
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6639
        if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) {
6640
          sprintf(tmpFile, "%s-%d",
6641
                  g_queryInfo.specifiedQueryInfo.result[i], pThreadInfo->threadID);
6642 6643 6644 6645 6646 6647
        }
        getResult(res, tmpFile);
      }
    }
  }
  taos_free_result(res);
6648

6649
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6650 6651
    taos_unsubscribe(tsub[i],
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
6652
  }
6653

6654
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
6655 6656 6657
  return NULL;
}

6658
static int subscribeTestProcess() {
6659
  setupForAnsiEscape();
6660
  printfQueryMeta();
6661
  resetAfterAnsiEscape();
6662

6663 6664
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
6665
    (void) getchar();
Y
yihaoDeng 已提交
6666
  }
6667

6668 6669 6670 6671 6672
  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
6673
          g_queryInfo.port);
6674
  if (taos == NULL) {
6675 6676
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6677 6678 6679
    exit(-1);
  }

6680
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6681 6682
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6683 6684 6685
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6686 6687
  }

6688 6689
  taos_close(taos); // TODO: workaround to use separate taos connection;

6690 6691 6692
  pthread_t  *pids = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from super table
6693 6694
  if ((g_queryInfo.specifiedQueryInfo.sqlCount <= 0) ||
          (g_queryInfo.specifiedQueryInfo.concurrent <= 0)) {
6695 6696 6697
    errorPrint("%s() LN%d, query sqlCount %"PRIu64" or concurrent %"PRIu64" is not correct.\n",
              __func__, __LINE__,
              g_queryInfo.specifiedQueryInfo.sqlCount,
6698
              g_queryInfo.specifiedQueryInfo.concurrent);
6699 6700 6701
    exit(-1);
  }

6702 6703
  pids  = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(pthread_t));
  infos = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(threadInfo));
6704
  if ((NULL == pids) || (NULL == infos)) {
6705
      errorPrint("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__);
6706
      exit(-1);
6707
  }
6708

6709
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6710 6711
      threadInfo *t_info = infos + i;
      t_info->threadID = i;
6712
      t_info->taos = NULL;  // TODO: workaround to use separate taos connection;
6713
      pthread_create(pids + i, NULL, specifiedSubscribe, t_info);
H
hzcheng 已提交
6714
  }
6715

6716
  //==== create sub threads for query from sub table
6717 6718
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
6719 6720 6721
  if ((g_queryInfo.superQueryInfo.sqlCount > 0)
          && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
    pidsOfSub  = malloc(g_queryInfo.superQueryInfo.threadCnt *
6722
            sizeof(pthread_t));
6723
    infosOfSub = malloc(g_queryInfo.superQueryInfo.threadCnt *
6724
            sizeof(threadInfo));
6725
    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6726 6727 6728
      errorPrint("%s() LN%d, malloc failed for create threads\n",
              __func__, __LINE__);
      // taos_close(taos);
6729
      exit(-1);
S
Shuaiqiang Chang 已提交
6730
    }
6731

6732
    uint64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
6733
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6734

6735
    uint64_t a = ntables / threads;
6736 6737 6738 6739
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6740

6741
    uint64_t b = 0;
6742 6743 6744
    if (threads != 0) {
      b = ntables % threads;
    }
6745

6746
    uint64_t startFrom = 0;
6747
    for (int i = 0; i < threads; i++) {
6748 6749
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6750

6751 6752 6753 6754
      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;
6755
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6756
      pthread_create(pidsOfSub + i, NULL, superSubscribe, t_info);
H
hzcheng 已提交
6757
    }
6758

6759
    g_queryInfo.superQueryInfo.threadCnt = threads;
6760

6761
    for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6762 6763
      pthread_join(pidsOfSub[i], NULL);
    }
H
hzcheng 已提交
6764
  }
6765

6766
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6767
    pthread_join(pids[i], NULL);
6768
  }
H
hzcheng 已提交
6769

6770
  tmfree((char*)pids);
6771
  tmfree((char*)infos);
H
hzcheng 已提交
6772

6773
  tmfree((char*)pidsOfSub);
6774
  tmfree((char*)infosOfSub);
6775
//   taos_close(taos);
6776
  return 0;
H
hzcheng 已提交
6777 6778
}

6779
static void initOfInsertMeta() {
6780
  memset(&g_Dbs, 0, sizeof(SDbs));
6781

6782
  // set default values
6783
  tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6784
  g_Dbs.port = 6030;
6785 6786
  tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
6787
  g_Dbs.threadCount = 2;
6788 6789

  g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
6790 6791
}

6792
static void initOfQueryMeta() {
6793
  memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo));
6794

6795
  // set default values
6796
  tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6797
  g_queryInfo.port = 6030;
6798 6799
  tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
L
Liu Tao 已提交
6800 6801
}

6802
static void setParaFromArg(){
6803
  if (g_args.host) {
6804
    tstrncpy(g_Dbs.host, g_args.host, MAX_HOSTNAME_SIZE);
6805
  } else {
6806
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6807
  }
L
Liu Tao 已提交
6808

6809
  if (g_args.user) {
6810
    tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE);
6811
  }
6812 6813

  if (g_args.password) {
6814
    tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE);
6815 6816
  }

6817 6818
  if (g_args.port) {
    g_Dbs.port = g_args.port;
6819
  }
L
Liu Tao 已提交
6820

6821 6822 6823
  g_Dbs.threadCount = g_args.num_of_threads;
  g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;

6824 6825
  g_Dbs.dbCount = 1;
  g_Dbs.db[0].drop = 1;
6826

6827
  tstrncpy(g_Dbs.db[0].dbName, g_args.database, MAX_DB_NAME_SIZE);
6828
  g_Dbs.db[0].dbCfg.replica = g_args.replica;
6829
  tstrncpy(g_Dbs.db[0].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
L
Liu Tao 已提交
6830

6831
  tstrncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN);
6832 6833 6834 6835 6836

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

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

6838 6839
  char dataString[STRING_LEN];
  char **data_type = g_args.datatype;
6840

6841
  memset(dataString, 0, STRING_LEN);
L
Liu Tao 已提交
6842

6843 6844
  if (strcasecmp(data_type[0], "BINARY") == 0
          || strcasecmp(data_type[0], "BOOL") == 0
6845
          || strcasecmp(data_type[0], "NCHAR") == 0 ) {
6846
    g_Dbs.do_aggreFunc = false;
L
Liu Tao 已提交
6847
  }
H
hzcheng 已提交
6848

6849 6850 6851 6852 6853
  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;
6854
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
6855
    g_Dbs.queryMode = g_args.query_mode;
6856

6857 6858 6859 6860
    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;
6861
    tstrncpy(g_Dbs.db[0].superTbls[0].childTblPrefix,
6862 6863 6864
            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);
6865
    tstrncpy(g_Dbs.db[0].superTbls[0].startTimestamp,
6866
            "2017-07-14 10:40:00.000", MAX_TB_NAME_SIZE);
6867
    g_Dbs.db[0].superTbls[0].timeStampStep = DEFAULT_TIMESTAMP_STEP;
6868

6869
    g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT;
6870
    g_Dbs.db[0].superTbls[0].maxSqlLen = g_args.max_sql_len;
6871

6872 6873 6874 6875 6876
    g_Dbs.db[0].superTbls[0].columnCount = 0;
    for (int i = 0; i < MAX_NUM_DATATYPE; i++) {
      if (data_type[i] == NULL) {
        break;
      }
6877

6878
      tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
6879
              data_type[i], MAX_TB_NAME_SIZE);
6880
      g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary;
6881 6882
      g_Dbs.db[0].superTbls[0].columnCount++;
    }
6883

6884 6885 6886 6887 6888
    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);
6889
        g_Dbs.db[0].superTbls[0].columns[i].dataLen = 0;
6890 6891 6892
        g_Dbs.db[0].superTbls[0].columnCount++;
      }
    }
6893

6894
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType, "INT", MAX_TB_NAME_SIZE);
6895
    g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0;
6896

6897
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType, "BINARY", MAX_TB_NAME_SIZE);
6898 6899
    g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary;
    g_Dbs.db[0].superTbls[0].tagCount = 2;
6900
  } else {
6901 6902
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
    g_Dbs.db[0].superTbls[0].tagCount = 0;
H
hzcheng 已提交
6903
  }
6904 6905 6906 6907 6908 6909
}

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

6911 6912 6913
  /* Compile regular expression */
  if (regcomp(&regex, reg, cflags) != 0) {
    printf("Fail to compile regex\n");
H
Hui Li 已提交
6914 6915 6916
    exit(-1);
  }

6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940
  /* 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);
}

6941
static void querySqlFile(TAOS* taos, char* sqlFile)
6942 6943 6944 6945 6946 6947
{
  FILE *fp = fopen(sqlFile, "r");
  if (fp == NULL) {
    printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno));
    return;
  }
6948

6949 6950 6951 6952 6953 6954
  int       read_len = 0;
  char *    cmd = calloc(1, MAX_SQL_SIZE);
  size_t    cmd_len = 0;
  char *    line = NULL;
  size_t    line_len = 0;

6955
  double t = taosGetTimestampMs();
6956

6957
  while((read_len = tgetline(&line, &line_len, fp)) != -1) {
6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969
    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;
6970
    }
6971 6972

    memcpy(cmd + cmd_len, line, read_len);
6973
    verbosePrint("%s() LN%d cmd: %s\n", __func__, __LINE__, cmd);
6974 6975 6976
    if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE, false)) {
        errorPrint("%s() LN%d, queryDbExec %s failed!\n",
               __func__, __LINE__, cmd);
6977 6978 6979 6980 6981
        tmfree(cmd);
        tmfree(line);
        tmfclose(fp);
        return;
    }
6982 6983
    memset(cmd, 0, MAX_SQL_SIZE);
    cmd_len = 0;
H
hzcheng 已提交
6984 6985
  }

6986
  t = taosGetTimestampMs() - t;
6987
  printf("run %s took %.6f second(s)\n\n", sqlFile, t);
6988

6989 6990 6991 6992
  tmfree(cmd);
  tmfree(line);
  tmfclose(fp);
  return;
H
hzcheng 已提交
6993 6994
}

6995
static void testMetaFile() {
6996
    if (INSERT_TEST == g_args.test_mode) {
6997 6998
      if (g_Dbs.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir);
6999

7000
      insertTestProcess();
7001

7002
    } else if (QUERY_TEST == g_args.test_mode) {
7003 7004
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
7005

7006
      queryTestProcess();
7007

7008
    } else if (SUBSCRIBE_TEST == g_args.test_mode) {
7009 7010
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
7011

7012
      subscribeTestProcess();
7013

7014 7015 7016
    }  else {
      ;
    }
7017
}
7018

7019
static void queryResult() {
7020
  // query data
7021

7022 7023 7024 7025 7026
  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;
7027

7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 7056 7057 7058 7059 7060 7061 7062 7063
  //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);
7064 7065
}

7066 7067
static void testCmdLine() {

7068 7069 7070 7071 7072 7073 7074 7075 7076 7077
  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);
  }

7078 7079
  g_args.test_mode = INSERT_TEST;
  insertTestProcess();
7080

7081
  if (false == g_Dbs.insert_only)
7082
    queryResult();
7083 7084
}

7085 7086 7087
int main(int argc, char *argv[]) {
  parse_args(argc, argv, &g_args);

7088
  debugPrint("meta file: %s\n", g_args.metaFile);
7089 7090 7091

  if (g_args.metaFile) {
    initOfInsertMeta();
7092
    initOfQueryMeta();
7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105

    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(
7106 7107 7108 7109
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
7110
          g_Dbs.port);
7111
      querySqlFile(qtaos, g_args.sqlFile);
7112 7113 7114 7115 7116
      taos_close(qtaos);

    } else {
      testCmdLine();
    }
H
hzcheng 已提交
7117
  }
7118 7119

  return 0;
H
hzcheng 已提交
7120
}
7121