taosdemo.c 235.0 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 776
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        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 784 785 786 787
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        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 792 793 794 795
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        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) {
H
Haojun Liao 已提交
798
      if ((argc == i+1) ||
799
        (!isStringNumber(argv[i+1]))) {
H
Haojun Liao 已提交
800 801 802 803
        printHelp();
        errorPrint("%s", "\n\t-qt need a number following!\n");
        exit(EXIT_FAILURE);
      }
804
      arguments->query_times = atoi(argv[++i]);
805
    } else if (strcmp(argv[i], "-B") == 0) {
H
Haojun Liao 已提交
806
      if ((argc == i+1) ||
807
        (!isStringNumber(argv[i+1]))) {
H
Haojun Liao 已提交
808 809 810 811
        printHelp();
        errorPrint("%s", "\n\t-B need a number following!\n");
        exit(EXIT_FAILURE);
      }
812
      arguments->interlace_rows = atoi(argv[++i]);
813
    } else if (strcmp(argv[i], "-r") == 0) {
814 815 816 817 818 819
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-r need a number following!\n");
        exit(EXIT_FAILURE);
      }
820 821
      arguments->num_of_RPR = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-t") == 0) {
822 823 824 825 826 827
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-t need a number following!\n");
        exit(EXIT_FAILURE);
      }
828 829
      arguments->num_of_tables = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-n") == 0) {
830 831 832 833 834 835
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-n need a number following!\n");
        exit(EXIT_FAILURE);
      }
836 837
      arguments->num_of_DPT = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-d") == 0) {
H
Haojun Liao 已提交
838 839 840 841 842
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-d need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
843 844
      arguments->database = argv[++i];
    } else if (strcmp(argv[i], "-l") == 0) {
845 846 847 848 849 850
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-l need a number following!\n");
        exit(EXIT_FAILURE);
      }
851 852
      arguments->num_of_CPR = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-b") == 0) {
853
      sptr = arguments->datatype;
854 855
      ++i;
      if (strstr(argv[i], ",") == NULL) {
856
        // only one col
857
        if (strcasecmp(argv[i], "INT")
858 859 860 861 862 863 864 865
                && 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")) {
866
          printHelp();
867
          errorPrint("%s", "-b: Invalid data_type!\n");
868
          exit(EXIT_FAILURE);
869
        }
870
        sptr[0] = argv[i];
871
      } else {
872
        // more than one col
873
        int index = 0;
874
        char *dupstr = strdup(argv[i]);
875 876
        char *running = dupstr;
        char *token = strsep(&running, ",");
877
        while(token != NULL) {
878
          if (strcasecmp(token, "INT")
879 880 881 882 883 884 885 886
                  && strcasecmp(token, "FLOAT")
                  && strcasecmp(token, "TINYINT")
                  && strcasecmp(token, "BOOL")
                  && strcasecmp(token, "SMALLINT")
                  && strcasecmp(token, "BIGINT")
                  && strcasecmp(token, "DOUBLE")
                  && strcasecmp(token, "BINARY")
                  && strcasecmp(token, "NCHAR")) {
887
            printHelp();
888
            free(dupstr);
889
            errorPrint("%s", "-b: Invalid data_type!\n");
890
            exit(EXIT_FAILURE);
H
hzcheng 已提交
891
          }
892 893 894
          sptr[index++] = token;
          token = strsep(&running, ",");
          if (index >= MAX_NUM_DATATYPE) break;
S
TD-1057  
Shengliang Guan 已提交
895
        }
896
        free(dupstr);
897
        sptr[index] = NULL;
898
      }
899
    } else if (strcmp(argv[i], "-w") == 0) {
900
      if ((argc == i+1) ||
901
        (!isStringNumber(argv[i+1]))) {
902 903 904 905
        printHelp();
        errorPrint("%s", "\n\t-w need a number following!\n");
        exit(EXIT_FAILURE);
      }
906 907
      arguments->len_of_binary = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-m") == 0) {
H
Haojun Liao 已提交
908
      if ((argc == i+1) ||
909
        (!isStringNumber(argv[i+1]))) {
H
Haojun Liao 已提交
910 911 912 913
        printHelp();
        errorPrint("%s", "\n\t-m need a number following!\n");
        exit(EXIT_FAILURE);
      }
914
      arguments->tb_prefix = argv[++i];
915 916
    } else if (strcmp(argv[i], "-N") == 0) {
      arguments->use_metric = false;
917
    } else if (strcmp(argv[i], "-x") == 0) {
918
      arguments->insert_only = false;
919
    } else if (strcmp(argv[i], "-y") == 0) {
920
      arguments->answer_yes = true;
921 922
    } else if (strcmp(argv[i], "-g") == 0) {
      arguments->debug_print = true;
923 924
    } else if (strcmp(argv[i], "-gg") == 0) {
      arguments->verbose_print = true;
925 926
    } else if (strcmp(argv[i], "-pp") == 0) {
      arguments->performance_print = true;
927
    } else if (strcmp(argv[i], "-O") == 0) {
928 929 930 931 932 933
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-O need a number following!\n");
        exit(EXIT_FAILURE);
      }
934

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1148 1149 1150
  getResult(res, resultFileName);
  taos_free_result(res);
}
H
hzcheng 已提交
1151

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  SHOW_PARSE_RESULT_END();
1452 1453

  return 0;
1454 1455 1456
}

static void printfInsertMetaToFile(FILE* fp) {
1457 1458

  SHOW_PARSE_RESULT_START_TO_FILE(fp);
1459

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

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

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

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

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

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

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

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

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

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

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

1620
  SHOW_PARSE_RESULT_END_TO_FILE(fp);
1621 1622 1623
}

static void printfQueryMeta() {
1624

1625
  SHOW_PARSE_RESULT_START();
1626

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

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

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
      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",
1682
        g_queryInfo.superQueryInfo.subscribeInterval);
1683
      printf("restart:        \033[33m%d\033[0m\n",
1684
        g_queryInfo.superQueryInfo.subscribeRestart);
1685
      printf("keepProgress:   \033[33m%d\033[0m\n",
1686
        g_queryInfo.superQueryInfo.subscribeKeepProgress);
1687

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

1696
  SHOW_PARSE_RESULT_END();
1697 1698
}

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

1731
static void xDumpFieldToFile(FILE* fp, const char* val,
1732
        TAOS_FIELD* field, int32_t length, int precision) {
1733

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

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

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

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

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

  TAOS_FIELD *fields = taos_fetch_fields(res);

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

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

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

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

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

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

  return count;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2044
    memset(base64_buf, 0, INPUT_BUF_LEN);
2045

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

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

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

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

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

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

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

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

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

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

2127
    return 0;
2128 2129
}

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

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

2142 2143 2144
  return dataBuf;
}

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

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

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

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

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

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

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

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

  superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow;
2290

2291 2292 2293 2294
  return 0;
}


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

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

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

  char* childTblName = *childTblNameOfSuperTbl;
2306 2307

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

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

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

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

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

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

  taos_free_result(res);
  return 0;
}

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

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

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

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

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

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

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

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

  calcRowLen(superTbls);

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

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

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

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

  int  lenOfOneRow = 0;
2473 2474 2475

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

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

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

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

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

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

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

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

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

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

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

  superTbl->lenOfTagOfOneRow = lenOfTagOfOneRow;

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

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

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

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

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

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

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

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

    int validStbCount = 0;

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

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

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

      validStbCount ++;
2745
    }
2746 2747

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

  taos_close(taos);
  return 0;
}

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

  int64_t  lastPrintTime = taosGetTimestampMs();

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

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

  int len = 0;
  int batchNum = 0;
2772

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

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

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

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

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

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

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

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

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

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

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

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

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

  return 0;
2921 2922
}

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

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

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

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

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

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

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

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

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

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

3013
  while((readLen = tgetline(&line, &n, fp)) != -1) {
3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025
    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) {
3026
      char *tmp = realloc(tagDataBuf,
3027
              (size_t)tagCount*1.5*superTblInfo->lenOfTagOfOneRow);
3028 3029 3030
      if (tmp != NULL) {
        tagDataBuf = tmp;
        tagCount = (int)(tagCount*1.5);
3031
        memset(tagDataBuf + count*superTblInfo->lenOfTagOfOneRow,
3032
                0, (size_t)((tagCount-count)*superTblInfo->lenOfTagOfOneRow));
3033 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
      } 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
*/
3060
static int readSampleFromCsvFileToMem(
3061
        SSuperTable* superTblInfo) {
3062 3063 3064 3065
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
  int getRows = 0;
3066

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

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

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

    if (readLen == 0) {
      continue;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

3197
  superTbls->columnCount = index;
3198

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

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

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

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

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

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

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

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

3268 3269
  superTbls->tagCount = index;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  ret = true;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4391
  ret = true;
H
hzcheng 已提交
4392

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

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

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

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

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

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

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

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

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

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

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

4509
  int    dataLen = 0;
4510

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

4517
  (*sampleUsePos)++;
4518

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4676 4677 4678
  return 0;
}

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

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

  return affectedRows;
}

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

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

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

4739 4740
  char *pstr = buffer;

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

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

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

4756
    int64_t retLen = 0;
4757

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

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

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

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

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

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

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

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

4817 4818 4819
      if (len > remainderBufLen)
        break;

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

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

    startFrom ++;
4830

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

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

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

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

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

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

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

  tstrncpy(buffer, headBuf, len + 1);

4904 4905 4906
  return len;
}

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

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

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

  pstr += headLen;
  *pRemainderBufLen -= headLen;

4932
  int64_t dataLen = 0;
4933

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

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

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

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

  return k;
}

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

  int ncols_per_record = 1; // count first col ts

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

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

4989
  int64_t k = 0;
4990

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

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

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

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

5008 5009
  return k;
}
5010

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

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

5024 5025
  uint64_t insertRows;
  uint64_t interlaceRows;
5026 5027

  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5028

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

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

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

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

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

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

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

5068
  char tableName[TSDB_TABLE_NAME_LEN];
5069 5070 5071 5072

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

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

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

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

5084
  uint64_t tableSeq = pThreadInfo->start_table_from;
5085

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

  int64_t startTime = pThreadInfo->start_time;

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

5094 5095
  uint64_t batchPerTbl = interlaceRows;
  uint64_t batchPerTblTimes;
5096

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

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

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

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

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

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

5126
    uint64_t recOfBatch = 0;
5127

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

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

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

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

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

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

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

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

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

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

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

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

5201
    startTs = taosGetTimestampMs();
5202

5203
    int64_t affectedRows = execInsert(pThreadInfo, buffer, recOfBatch);
5204

5205
    endTs = taosGetTimestampMs();
5206 5207
    uint64_t delay = endTs - startTs;
    performancePrint("%s() LN%d, insert execution time is %"PRIu64"ms\n",
5208
            __func__, __LINE__, delay);
5209 5210 5211
    verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5212 5213 5214 5215 5216 5217

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

5218 5219
    if (recOfBatch != affectedRows) {
        errorPrint("[%d] %s() LN%d execInsert insert %"PRIu64", affected rows: %"PRId64"\n%s\n",
5220 5221
                pThreadInfo->threadID, __func__, __LINE__,
                recOfBatch, affectedRows, buffer);
5222
        goto free_of_interlace;
5223
    }
5224

5225
    pThreadInfo->totalAffectedRows += affectedRows;
5226

5227 5228
    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
5229
      printf("thread[%d] has currently inserted rows: %"PRIu64 ", affected rows: %"PRIu64 "\n",
5230 5231 5232
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5233 5234
      lastPrintTime = currentPrintTime;
    }
5235

5236
    if ((insert_interval) && flagSleep) {
5237
      et = taosGetTimestampMs();
5238

5239 5240
      if (insert_interval > (et - st) ) {
        int sleepTime = insert_interval - (et -st);
5241
        performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
5242
                    __func__, __LINE__, sleepTime);
5243 5244 5245
        taosMsleep(sleepTime); // ms
        sleepTimeTotal += insert_interval;
      }
5246
    }
5247 5248
  }

5249
free_of_interlace:
5250
  tmfree(buffer);
5251
  printStatPerThread(pThreadInfo);
5252 5253 5254
  return NULL;
}

5255 5256 5257 5258 5259 5260 5261 5262
// 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
*/
5263
static void* syncWriteProgressive(threadInfo *pThreadInfo) {
5264
  debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__);
5265

5266
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5267
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5268

5269
  char* buffer = calloc(maxSqlLen, 1);
5270
  if (NULL == buffer) {
5271
    errorPrint( "Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5272 5273
              maxSqlLen,
              strerror(errno));
5274 5275
    return NULL;
  }
5276

5277 5278 5279
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5280

5281
  int64_t timeStampStep =
5282
      superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
5283
/*  int insert_interval =
5284
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5285 5286
  uint64_t st = 0;
  uint64_t et = 0xffffffff;
5287
  */
5288

5289 5290
  pThreadInfo->totalInsertRows = 0;
  pThreadInfo->totalAffectedRows = 0;
5291

5292
  pThreadInfo->samplePos = 0;
5293

5294
  for (uint64_t tableSeq =
5295 5296
          pThreadInfo->start_table_from; tableSeq <= pThreadInfo->end_table_to;
        tableSeq ++) {
5297
    int64_t start_time = pThreadInfo->start_time;
5298

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

5302
    for (uint64_t i = 0; i < insertRows;) {
5303 5304 5305 5306 5307
        /*
      if (insert_interval) {
            st = taosGetTimestampMs();
      }
      */
5308

5309 5310
      char tableName[TSDB_TABLE_NAME_LEN];
      getTableName(tableName, pThreadInfo, tableSeq);
5311
      verbosePrint("%s() LN%d: tid=%d seq=%"PRId64" tableName=%s\n",
5312 5313
             __func__, __LINE__,
             pThreadInfo->threadID, tableSeq, tableName);
5314

5315
      int64_t remainderBufLen = maxSqlLen;
5316 5317 5318 5319 5320 5321 5322 5323
      char *pstr = buffer;
      int nInsertBufLen = strlen("insert into ");

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

      pstr += len;
      remainderBufLen -= len;

5324
      int64_t generated = generateProgressiveDataBuffer(
5325 5326 5327 5328
              tableName, tableSeq, pThreadInfo, pstr, insertRows,
            i, start_time,
            &(pThreadInfo->samplePos),
            &remainderBufLen);
5329 5330 5331
      if (generated > 0)
        i += generated;
      else
5332
        goto free_of_progressive;
5333

5334
      start_time +=  generated * timeStampStep;
5335
      pThreadInfo->totalInsertRows += generated;
5336

5337
      startTs = taosGetTimestampMs();
5338

5339
      int64_t affectedRows = execInsert(pThreadInfo, buffer, generated);
5340

5341
      endTs = taosGetTimestampMs();
5342
      uint64_t delay = endTs - startTs;
5343
      performancePrint("%s() LN%d, insert execution time is %"PRId64"ms\n",
5344
              __func__, __LINE__, delay);
5345 5346 5347
      verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5348

5349 5350 5351 5352
      if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
      if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
      pThreadInfo->cntDelay++;
      pThreadInfo->totalDelay += delay;
5353

5354 5355 5356 5357 5358
      if (affectedRows < 0) {
        errorPrint("%s() LN%d, affected rows: %"PRId64"\n",
                __func__, __LINE__, affectedRows);
        goto free_of_progressive;
      }
5359 5360 5361

      pThreadInfo->totalAffectedRows += affectedRows;

5362 5363
      int64_t  currentPrintTime = taosGetTimestampMs();
      if (currentPrintTime - lastPrintTime > 30*1000) {
5364
        printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
5365 5366 5367
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5368 5369 5370
        lastPrintTime = currentPrintTime;
      }

5371
      if (i >= insertRows)
5372
        break;
5373
/*
5374
      if (insert_interval) {
5375
        et = taosGetTimestampMs();
5376

5377 5378
        if (insert_interval > ((et - st)) ) {
            int sleep_time = insert_interval - (et -st);
5379 5380
            performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
                    __func__, __LINE__, sleep_time);
5381 5382
            taosMsleep(sleep_time); // ms
        }
5383
      }
5384
      */
5385 5386
    }   // num_of_DPT

5387 5388
    if (g_args.verbose_print) {
      if ((tableSeq == pThreadInfo->ntables - 1) && superTblInfo &&
5389 5390
        (0 == strncasecmp(
                    superTblInfo->dataSource, "sample", strlen("sample")))) {
5391
          verbosePrint("%s() LN%d samplePos=%"PRId64"\n",
5392
                  __func__, __LINE__, pThreadInfo->samplePos);
5393
      }
5394
    }
5395
  } // tableSeq
5396

5397
free_of_progressive:
5398
  tmfree(buffer);
5399
  printStatPerThread(pThreadInfo);
5400
  return NULL;
H
Hui Li 已提交
5401 5402
}

5403 5404
static void* syncWrite(void *sarg) {

5405 5406
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5407

5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419
  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;
  }
5420

5421
  if (interlaceRows > 0) {
5422
    // interlace mode
5423
    return syncWriteInterlace(pThreadInfo);
5424 5425
  } else {
    // progressive mode
5426
    return syncWriteProgressive(pThreadInfo);
5427
  }
5428

5429 5430
}

5431
static void callBack(void *param, TAOS_RES *res, int code) {
5432 5433
  threadInfo* pThreadInfo = (threadInfo*)param;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5434

5435 5436
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5437
  if (insert_interval) {
5438 5439 5440
    pThreadInfo->et = taosGetTimestampMs();
    if ((pThreadInfo->et - pThreadInfo->st) < insert_interval) {
      taosMsleep(insert_interval - (pThreadInfo->et - pThreadInfo->st)); // ms
5441
    }
H
Hui Li 已提交
5442
  }
5443

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

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

5474
    if (pThreadInfo->counter >= pThreadInfo->superTblInfo->insertRows) {
5475
      break;
H
Hui Li 已提交
5476 5477
    }
  }
5478

5479
  if (insert_interval) {
5480
    pThreadInfo->st = taosGetTimestampMs();
5481
  }
5482
  taos_query_a(pThreadInfo->taos, buffer, callBack, pThreadInfo);
5483
  free(buffer);
H
Hui Li 已提交
5484

5485
  taos_free_result(res);
H
Hui Li 已提交
5486 5487
}

5488
static void *asyncWrite(void *sarg) {
5489 5490
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5491

5492 5493 5494
  pThreadInfo->st = 0;
  pThreadInfo->et = 0;
  pThreadInfo->lastTs = pThreadInfo->start_time;
5495

5496
  int insert_interval =
5497
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5498
  if (insert_interval) {
5499
    pThreadInfo->st = taosGetTimestampMs();
H
Hui Li 已提交
5500
  }
5501
  taos_query_a(pThreadInfo->taos, "show databases", callBack, pThreadInfo);
5502

5503
  tsem_wait(&(pThreadInfo->lock_sem));
H
Hui Li 已提交
5504 5505 5506 5507

  return NULL;
}

5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533
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;
}

5534
static void startMultiThreadInsertData(int threads, char* db_name,
5535
        char* precision,SSuperTable* superTblInfo) {
5536

5537 5538
  pthread_t *pids = malloc(threads * sizeof(pthread_t));
  assert(pids != NULL);
H
Hui Li 已提交
5539

5540 5541
  threadInfo *infos = malloc(threads * sizeof(threadInfo));
  assert(infos != NULL);
5542

5543 5544
  memset(pids, 0, threads * sizeof(pthread_t));
  memset(infos, 0, threads * sizeof(threadInfo));
5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561

  //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 {
5562
      errorPrint("Not support precision: %s\n", precision);
5563 5564 5565 5566
      exit(-1);
    }
  }

5567
  int64_t start_time;
5568 5569
  if (superTblInfo) {
    if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
5570
        start_time = taosGetTimestamp(timePrec);
5571
    } else {
5572
      if (TSDB_CODE_SUCCESS != taosParseTime(
5573 5574 5575 5576 5577
        superTblInfo->startTimestamp,
        &start_time,
        strlen(superTblInfo->startTimestamp),
        timePrec, 0)) {
          ERROR_EXIT("failed to parse time!\n");
5578
      }
5579
    }
5580
  } else {
5581
     start_time = 1500000000000;
5582 5583
  }

5584
  int64_t start = taosGetTimestampMs();
5585

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

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

  TAOS* taos = taos_connect(
5607 5608
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
5609
  if (NULL == taos) {
5610
    errorPrint("%s() LN%d, connect to server fail , reason: %s\n",
5611
                __func__, __LINE__, taos_errstr(NULL));
5612 5613 5614
    exit(-1);
  }

5615 5616
  int ntables = 0;
  int startFrom;
5617

5618
  if (superTblInfo) {
5619 5620
    int64_t limit;
    uint64_t offset;
5621

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

5627
    if (superTblInfo->childTblExists == TBL_ALREADY_EXISTS) {
5628 5629
      if ((superTblInfo->childTblLimit < 0)
          || ((superTblInfo->childTblOffset + superTblInfo->childTblLimit)
5630
            > (superTblInfo->childTblCount))) {
5631 5632 5633 5634 5635 5636
        superTblInfo->childTblLimit =
            superTblInfo->childTblCount - superTblInfo->childTblOffset;
      }

      offset = superTblInfo->childTblOffset;
      limit = superTblInfo->childTblLimit;
5637
    } else {
5638 5639
      limit = superTblInfo->childTblCount;
      offset = 0;
5640 5641
    }

5642 5643 5644
    ntables = limit;
    startFrom = offset;

5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655
    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)
5656
            && (0 == superTblInfo->childTblLimit)) {
5657 5658 5659 5660 5661 5662 5663
      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();
      }
    }

5664
    superTblInfo->childTblName = (char*)calloc(1,
5665
        limit * TSDB_TABLE_NAME_LEN);
5666
    if (superTblInfo->childTblName == NULL) {
5667
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
5668 5669 5670 5671
      taos_close(taos);
      exit(-1);
    }

5672
    uint64_t childTblCount;
5673 5674 5675 5676 5677 5678
    getChildNameOfSuperTableWithLimitAndOffset(
        taos,
        db_name, superTblInfo->sTblName,
        &superTblInfo->childTblName, &childTblCount,
        limit,
        offset);
5679 5680 5681
  } else {
    ntables = g_args.num_of_tables;
    startFrom = 0;
5682
  }
5683

5684 5685
  taos_close(taos);

5686
  uint64_t a = ntables / threads;
5687 5688 5689 5690 5691
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

5692
  uint64_t b = 0;
5693 5694 5695 5696
  if (threads != 0) {
    b = ntables % threads;
  }

5697 5698 5699 5700 5701 5702
  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 已提交
5703
  for (int i = 0; i < threads; i++) {
5704
    threadInfo *t_info = infos + i;
H
Hui Li 已提交
5705 5706
    t_info->threadID = i;
    tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE);
5707
    t_info->time_precision = timePrec;
5708 5709 5710
    t_info->superTblInfo = superTblInfo;

    t_info->start_time = start_time;
5711
    t_info->minDelay = UINT64_MAX;
5712

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

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

H
Hui Li 已提交
5750 5751 5752 5753
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

5754 5755 5756 5757
  uint64_t totalDelay = 0;
  uint64_t maxDelay = 0;
  uint64_t minDelay = UINT64_MAX;
  uint64_t cntDelay = 1;
5758 5759
  double  avgDelay = 0;

H
Hui Li 已提交
5760
  for (int i = 0; i < threads; i++) {
5761 5762
    threadInfo *t_info = infos + i;

S
TD-1057  
Shengliang Guan 已提交
5763
    tsem_destroy(&(t_info->lock_sem));
5764 5765
    taos_close(t_info->taos);

5766
    debugPrint("%s() LN%d, [%d] totalInsert=%"PRIu64" totalAffected=%"PRIu64"\n",
5767 5768 5769
            __func__, __LINE__,
            t_info->threadID, t_info->totalInsertRows,
            t_info->totalAffectedRows);
5770
    if (superTblInfo) {
5771 5772
        superTblInfo->totalAffectedRows += t_info->totalAffectedRows;
        superTblInfo->totalInsertRows += t_info->totalInsertRows;
5773
    } else {
5774 5775
        g_args.totalAffectedRows += t_info->totalAffectedRows;
        g_args.totalInsertRows += t_info->totalInsertRows;
5776
    }
5777 5778 5779 5780

    totalDelay  += t_info->totalDelay;
    cntDelay   += t_info->cntDelay;
    if (t_info->maxDelay > maxDelay) maxDelay = t_info->maxDelay;
5781
    if (t_info->minDelay < minDelay) minDelay = t_info->minDelay;
H
Hui Li 已提交
5782
  }
5783
  cntDelay -= 1;
H
Hui Li 已提交
5784

5785
  if (cntDelay == 0)    cntDelay = 1;
5786 5787
  avgDelay = (double)totalDelay / cntDelay;

5788 5789
  int64_t end = taosGetTimestampMs();
  int64_t t = end - start;
5790 5791

  if (superTblInfo) {
5792
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
5793 5794 5795 5796
          t / 1000.0, superTblInfo->totalInsertRows,
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
5797 5798 5799 5800

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

5822
  fprintf(stderr, "insert delay, avg: %10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
5823
          avgDelay, maxDelay, minDelay);
5824 5825
  if (g_fpOfInsertResult) {
    fprintf(g_fpOfInsertResult, "insert delay, avg:%10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
5826
          avgDelay, maxDelay, minDelay);
5827
  }
5828

5829 5830
  //taos_close(taos);

H
Hui Li 已提交
5831
  free(pids);
5832
  free(infos);
H
Hui Li 已提交
5833 5834
}

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

5848
    int num_of_DPT;
5849
/*  if (rinfo->superTblInfo) {
5850 5851
    num_of_DPT = rinfo->superTblInfo->insertRows; //  nrecords_per_table;
  } else {
5852
  */
5853
      num_of_DPT = g_args.num_of_DPT;
5854
//  }
5855

5856
  int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
H
hzcheng 已提交
5857
  int totalData = num_of_DPT * num_of_tables;
5858
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5859 5860 5861 5862 5863 5864 5865 5866

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

5867
  for (uint64_t j = 0; j < n; j++) {
H
hzcheng 已提交
5868
    double totalT = 0;
5869 5870 5871
    uint64_t count = 0;
    for (uint64_t i = 0; i < num_of_tables; i++) {
      sprintf(command, "select %s from %s%"PRIu64" where ts>= %" PRIu64,
5872
              aggreFunc[j], tb_prefix, i, sTime);
H
hzcheng 已提交
5873

5874
      double t = taosGetTimestampMs();
S
Shuaiqiang Chang 已提交
5875 5876
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);
H
hzcheng 已提交
5877

S
Shuaiqiang Chang 已提交
5878
      if (code != 0) {
5879
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
5880
        taos_free_result(pSql);
H
hzcheng 已提交
5881
        taos_close(taos);
5882
        fclose(fp);
5883
        return NULL;
H
hzcheng 已提交
5884 5885
      }

5886
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
5887 5888 5889
        count++;
      }

5890
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
5891 5892
      totalT += t;

S
Shuaiqiang Chang 已提交
5893
      taos_free_result(pSql);
H
hzcheng 已提交
5894 5895 5896
    }

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

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

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

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

  for (int j = 0; j < n; j++) {
sangshuduo's avatar
sangshuduo 已提交
5931
    char condition[BUFFER_SIZE - 30] = "\0";
B
Bomin Zhang 已提交
5932
    char tempS[64] = "\0";
H
hzcheng 已提交
5933 5934 5935 5936 5937

    int m = 10 < num_of_tables ? 10 : num_of_tables;

    for (int i = 1; i <= m; i++) {
      if (i == 1) {
5938
        sprintf(tempS, "t1 = %d", i);
H
hzcheng 已提交
5939
      } else {
5940
        sprintf(tempS, " or t1 = %d ", i);
H
hzcheng 已提交
5941 5942 5943
      }
      strcat(condition, tempS);

L
liu0x54 已提交
5944
      sprintf(command, "select %s from meters where %s", aggreFunc[j], condition);
H
hzcheng 已提交
5945 5946 5947 5948

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

5949
      double t = taosGetTimestampMs();
H
hzcheng 已提交
5950

S
Shuaiqiang Chang 已提交
5951 5952 5953 5954
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);

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

5967
      fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n",
5968 5969
              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 已提交
5970

S
Shuaiqiang Chang 已提交
5971
      taos_free_result(pSql);
H
hzcheng 已提交
5972 5973 5974 5975
    }
    fprintf(fp, "\n");
  }
  fclose(fp);
5976
#endif
H
hzcheng 已提交
5977 5978 5979
  return NULL;
}

H
Hui Li 已提交
5980

5981
static int insertTestProcess() {
5982

5983 5984 5985
  setupForAnsiEscape();
  int ret = printfInsertMeta();
  resetAfterAnsiEscape();
5986

5987 5988 5989
  if (ret == -1)
    exit(EXIT_FAILURE);

5990
  debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile);
5991 5992
  g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a");
  if (NULL == g_fpOfInsertResult) {
5993
    errorPrint( "Failed to open %s for save result\n", g_Dbs.resultFile);
5994 5995
    return -1;
  }
5996

5997 5998
  if (g_fpOfInsertResult)
    printfInsertMetaToFile(g_fpOfInsertResult);
5999

6000 6001 6002 6003
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
6004

6005 6006 6007
  init_rand_data();

  // create database and super tables
6008
  if(createDatabasesAndStables() != 0) {
6009 6010
    if (g_fpOfInsertResult)
      fclose(g_fpOfInsertResult);
6011 6012
    return -1;
  }
6013 6014

  // pretreatement
6015
  prepareSampleData();
6016

6017 6018 6019 6020
  double start;
  double end;

  // create child tables
6021
  start = taosGetTimestampMs();
6022
  createChildTables();
6023
  end = taosGetTimestampMs();
6024

6025
  if (g_totalChildTables > 0) {
6026
    fprintf(stderr, "Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
6027
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6028 6029
    if (g_fpOfInsertResult) {
      fprintf(g_fpOfInsertResult,
6030
            "Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
6031
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6032
    }
6033
  }
6034

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

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

6074 6075 6076
  return 0;
}

6077 6078
static void *specifiedTableQuery(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6079

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

6096 6097
  char sqlStr[MAX_DB_NAME_SIZE + 5];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6098 6099
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6100 6101 6102 6103
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
    return NULL;
  }
6104

6105 6106
  uint64_t st = 0;
  uint64_t et = 0;
6107

6108
  uint64_t queryTimes = g_queryInfo.specifiedQueryInfo.queryTimes;
6109

6110 6111 6112
  uint64_t totalQueried = 0;
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
6113

6114
  while(queryTimes --) {
6115
    if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) <
6116
            (int64_t)g_queryInfo.specifiedQueryInfo.queryInterval) {
6117
      taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval - (et - st)); // ms
6118 6119
    }

6120
    st = taosGetTimestampMs();
6121

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

6148 6149 6150 6151
    } else {
      errorPrint("%s() LN%d, unknown query mode: %s\n",
        __func__, __LINE__, g_queryInfo.queryMode);
      return NULL;
6152
    }
6153 6154
    totalQueried ++;
    g_queryInfo.specifiedQueryInfo.totalQueried ++;
6155

6156
    et = taosGetTimestampMs();
6157

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

6173
static void replaceChildTblName(char* inSql, char* outSql, int tblIndex) {
6174 6175
  char sourceString[32] = "xxxx";
  char subTblName[MAX_TB_NAME_SIZE*3];
6176 6177
  sprintf(subTblName, "%s.%s",
          g_queryInfo.dbName,
6178
          g_queryInfo.superQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN);
6179 6180

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

6182 6183
  char* pos = strstr(inSql, sourceString);
  if (0 == pos) {
6184
    return;
H
Hui Li 已提交
6185
  }
6186

6187
  tstrncpy(outSql, inSql, pos - inSql + 1);
6188
  //printf("1: %s\n", outSql);
6189 6190 6191 6192
  strcat(outSql, subTblName);
  //printf("2: %s\n", outSql);
  strcat(outSql, pos+strlen(sourceString));
  //printf("3: %s\n", outSql);
H
Hui Li 已提交
6193 6194
}

6195
static void *superTableQuery(void *sarg) {
6196
  char sqlstr[1024];
6197
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6198

6199
  if (pThreadInfo->taos == NULL) {
6200 6201 6202 6203 6204 6205 6206 6207
    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",
6208
            pThreadInfo->threadID, taos_errstr(NULL));
6209 6210
      return NULL;
    } else {
6211
      pThreadInfo->taos = taos;
6212 6213 6214
    }
  }

6215 6216
  uint64_t st = 0;
  uint64_t et = (int64_t)g_queryInfo.superQueryInfo.queryInterval;
6217

6218 6219 6220
  uint64_t queryTimes = g_queryInfo.superQueryInfo.queryTimes;
  uint64_t totalQueried = 0;
  uint64_t  startTs = taosGetTimestampMs();
6221

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

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

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

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

6265 6266 6267
  return NULL;
}

6268
static int queryTestProcess() {
6269 6270 6271 6272

  setupForAnsiEscape();
  printfQueryMeta();
  resetAfterAnsiEscape();
6273 6274 6275 6276 6277 6278

  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
6279
          g_queryInfo.port);
6280
  if (taos == NULL) {
6281 6282
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6283 6284 6285
    exit(-1);
  }

6286
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6287 6288
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6289 6290 6291
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6292
  }
6293

6294 6295 6296 6297
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
6298

6299
  printfQuerySystemInfo(taos);
6300

6301 6302 6303 6304 6305 6306
  if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
    if (convertHostToServAddr(
        g_queryInfo.host, g_queryInfo.port, &g_queryInfo.serv_addr) != 0)
      exit(-1);
  }

6307 6308 6309
  pthread_t  *pids  = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from specify table
6310 6311
  int nConcurrent = g_queryInfo.specifiedQueryInfo.concurrent;
  int nSqlCount = g_queryInfo.specifiedQueryInfo.sqlCount;
6312

6313
  uint64_t startTs = taosGetTimestampMs();
6314

6315 6316 6317 6318 6319 6320
  if ((nSqlCount > 0) && (nConcurrent > 0)) {

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

    if ((NULL == pids) || (NULL == infos)) {
6321
      taos_close(taos);
6322
      ERROR_EXIT("memory allocation failed for create threads\n");
6323
    }
6324

6325 6326 6327 6328 6329
    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;
6330

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

6333 6334 6335 6336
          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)) {
6337
            taos_close(taos);
6338 6339
            free(infos);
            free(pids);
6340 6341 6342
            errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
            return -1;
6343
          }
6344
        }
6345

6346
        t_info->taos = NULL;// TODO: workaround to use separate taos connection;
6347

6348
        pthread_create(pids + i * nSqlCount + j, NULL, specifiedTableQuery,
6349 6350
            t_info);
      }
6351
    }
6352
  } else {
6353
    g_queryInfo.specifiedQueryInfo.concurrent = 0;
6354
  }
6355

6356 6357
  taos_close(taos);

6358 6359 6360
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
  //==== create sub threads for query from all sub table of the super table
6361 6362 6363 6364
  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));
6365 6366

    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6367 6368
      free(infos);
      free(pids);
6369

6370
      ERROR_EXIT("memory allocation failed for create threads\n");
6371
    }
6372

6373
    uint64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
6374
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6375

6376
    uint64_t a = ntables / threads;
6377 6378 6379 6380
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6381

6382
    uint64_t b = 0;
6383 6384 6385
    if (threads != 0) {
      b = ntables % threads;
    }
6386

6387
    uint64_t startFrom = 0;
6388
    for (int i = 0; i < threads; i++) {
6389 6390
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6391

6392 6393 6394 6395
      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;
6396
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6397
      pthread_create(pidsOfSub + i, NULL, superTableQuery, t_info);
6398 6399
    }

6400
    g_queryInfo.superQueryInfo.threadCnt = threads;
6401
  } else {
6402
    g_queryInfo.superQueryInfo.threadCnt = 0;
6403
  }
6404

6405 6406 6407 6408 6409 6410
  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);
      }
    }
6411
  }
S
Shuaiqiang Chang 已提交
6412

6413
  tmfree((char*)pids);
6414
  tmfree((char*)infos);
6415

6416
  for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6417
    pthread_join(pidsOfSub[i], NULL);
H
hzcheng 已提交
6418
  }
H
Hui Li 已提交
6419

6420
  tmfree((char*)pidsOfSub);
6421
  tmfree((char*)infosOfSub);
6422

6423
//  taos_close(taos);// TODO: workaround to use separate taos connection;
6424
  uint64_t endTs = taosGetTimestampMs();
6425

6426
  uint64_t totalQueried = g_queryInfo.specifiedQueryInfo.totalQueried +
6427 6428
    g_queryInfo.superQueryInfo.totalQueried;

6429
  fprintf(stderr, "==== completed total queries: %"PRIu64", the QPS of all threads: %10.3f====\n",
6430
          totalQueried,
6431
          (double)(totalQueried/((endTs-startTs)/1000.0)));
6432 6433 6434
  return 0;
}

6435
static void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
6436
  if (res == NULL || taos_errno(res) != 0) {
6437 6438
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
6439 6440
    return;
  }
6441

6442
  getResult(res, (char*)param);
6443
  // tao_unscribe() will free result.
H
hzcheng 已提交
6444 6445
}

6446 6447
static TAOS_SUB* subscribeImpl(
        TAOS *taos, char *sql, char* topic, char* resultFileName) {
6448
  TAOS_SUB* tsub = NULL;
H
hzcheng 已提交
6449

6450
  if (ASYNC_QUERY_MODE == g_queryInfo.specifiedQueryInfo.mode) {
6451
    tsub = taos_subscribe(taos,
6452
            g_queryInfo.specifiedQueryInfo.subscribeRestart,
6453
            topic, sql, subscribe_callback, (void*)resultFileName,
6454
            g_queryInfo.specifiedQueryInfo.subscribeInterval);
6455
  } else {
6456
    tsub = taos_subscribe(taos,
6457
            g_queryInfo.specifiedQueryInfo.subscribeRestart,
6458
            topic, sql, NULL, NULL, 0);
6459
  }
6460

6461 6462 6463
  if (tsub == NULL) {
    printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
    return NULL;
6464
  }
6465

6466 6467
  return tsub;
}
H
hzcheng 已提交
6468

6469 6470
static void *superSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6471
  char subSqlstr[1024];
6472
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
H
hzcheng 已提交
6473

6474 6475 6476
  if (g_queryInfo.superQueryInfo.sqlCount == 0)
    return NULL;

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

6493 6494
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6495 6496
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6497 6498
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
6499 6500
    return NULL;
  }
6501

6502 6503 6504
  //int64_t st = 0;
  //int64_t et = 0;
  do {
6505 6506
    //if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) < g_queryInfo.specifiedQueryInfo.queryInterval) {
    //  taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval- (et - st)); // ms
6507
    //  //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6508 6509 6510 6511
    //}

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

  // start loop to consume result
  TAOS_RES* res = NULL;
6533
  while(1) {
6534
    for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
6535
      if (ASYNC_QUERY_MODE == g_queryInfo.superQueryInfo.mode) {
6536 6537
        continue;
      }
6538

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

6553
  for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
6554
    taos_unsubscribe(tsub[i], g_queryInfo.superQueryInfo.subscribeKeepProgress);
6555
  }
6556

6557
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
6558 6559 6560
  return NULL;
}

6561 6562
static void *specifiedSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6563
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
H
hzcheng 已提交
6564

6565 6566 6567
  if (g_queryInfo.specifiedQueryInfo.sqlCount == 0)
    return NULL;

6568
  if (pThreadInfo->taos == NULL) {
6569 6570 6571 6572 6573 6574 6575 6576
    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",
6577
            pThreadInfo->threadID, taos_errstr(NULL));
6578 6579
      return NULL;
    } else {
6580
      pThreadInfo->taos = taos;
6581 6582 6583
    }
  }

6584 6585
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6586
  debugPrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
6587 6588
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6589 6590
    return NULL;
  }
6591

6592 6593 6594
  //int64_t st = 0;
  //int64_t et = 0;
  do {
6595 6596
    //if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) < g_queryInfo.specifiedQueryInfo.queryInterval) {
    //  taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval- (et - st)); // ms
6597
    //  //printf("========sleep duration:%"PRIu64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6598 6599 6600 6601
    //}

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

  // start loop to consume result
  TAOS_RES* res = NULL;
6622
  while(1) {
6623
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6624
      if (ASYNC_QUERY_MODE == g_queryInfo.specifiedQueryInfo.mode) {
6625 6626
        continue;
      }
6627

6628
      res = taos_consume(tsub[i]);
6629 6630
      if (res) {
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6631
        if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) {
6632
          sprintf(tmpFile, "%s-%d",
6633
                  g_queryInfo.specifiedQueryInfo.result[i], pThreadInfo->threadID);
6634 6635 6636 6637 6638 6639
        }
        getResult(res, tmpFile);
      }
    }
  }
  taos_free_result(res);
6640

6641
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6642 6643
    taos_unsubscribe(tsub[i],
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
6644
  }
6645

6646
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
6647 6648 6649
  return NULL;
}

6650
static int subscribeTestProcess() {
6651
  setupForAnsiEscape();
6652
  printfQueryMeta();
6653
  resetAfterAnsiEscape();
6654

6655 6656
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
6657
    (void) getchar();
Y
yihaoDeng 已提交
6658
  }
6659

6660 6661 6662 6663 6664
  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
6665
          g_queryInfo.port);
6666
  if (taos == NULL) {
6667 6668
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6669 6670 6671
    exit(-1);
  }

6672
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6673 6674
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6675 6676 6677
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6678 6679
  }

6680 6681
  taos_close(taos); // TODO: workaround to use separate taos connection;

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

6694 6695
  pids  = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(pthread_t));
  infos = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(threadInfo));
6696
  if ((NULL == pids) || (NULL == infos)) {
6697
      errorPrint("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__);
6698
      exit(-1);
6699
  }
6700

6701
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6702 6703
      threadInfo *t_info = infos + i;
      t_info->threadID = i;
6704
      t_info->taos = NULL;  // TODO: workaround to use separate taos connection;
6705
      pthread_create(pids + i, NULL, specifiedSubscribe, t_info);
H
hzcheng 已提交
6706
  }
6707

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

6724
    uint64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
6725
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6726

6727
    uint64_t a = ntables / threads;
6728 6729 6730 6731
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6732

6733
    uint64_t b = 0;
6734 6735 6736
    if (threads != 0) {
      b = ntables % threads;
    }
6737

6738
    uint64_t startFrom = 0;
6739
    for (int i = 0; i < threads; i++) {
6740 6741
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6742

6743 6744 6745 6746
      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;
6747
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6748
      pthread_create(pidsOfSub + i, NULL, superSubscribe, t_info);
H
hzcheng 已提交
6749
    }
6750

6751
    g_queryInfo.superQueryInfo.threadCnt = threads;
6752

6753
    for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6754 6755
      pthread_join(pidsOfSub[i], NULL);
    }
H
hzcheng 已提交
6756
  }
6757

6758
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6759
    pthread_join(pids[i], NULL);
6760
  }
H
hzcheng 已提交
6761

6762
  tmfree((char*)pids);
6763
  tmfree((char*)infos);
H
hzcheng 已提交
6764

6765
  tmfree((char*)pidsOfSub);
6766
  tmfree((char*)infosOfSub);
6767
//   taos_close(taos);
6768
  return 0;
H
hzcheng 已提交
6769 6770
}

6771
static void initOfInsertMeta() {
6772
  memset(&g_Dbs, 0, sizeof(SDbs));
6773

6774
  // set default values
6775
  tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6776
  g_Dbs.port = 6030;
6777 6778
  tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
6779
  g_Dbs.threadCount = 2;
6780 6781

  g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
6782 6783
}

6784
static void initOfQueryMeta() {
6785
  memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo));
6786

6787
  // set default values
6788
  tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6789
  g_queryInfo.port = 6030;
6790 6791
  tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
L
Liu Tao 已提交
6792 6793
}

6794
static void setParaFromArg(){
6795
  if (g_args.host) {
6796
    tstrncpy(g_Dbs.host, g_args.host, MAX_HOSTNAME_SIZE);
6797
  } else {
6798
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6799
  }
L
Liu Tao 已提交
6800

6801
  if (g_args.user) {
6802
    tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE);
6803
  }
6804 6805

  if (g_args.password) {
6806
    tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE);
6807 6808
  }

6809 6810
  if (g_args.port) {
    g_Dbs.port = g_args.port;
6811
  }
L
Liu Tao 已提交
6812

6813 6814 6815
  g_Dbs.threadCount = g_args.num_of_threads;
  g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;

6816 6817
  g_Dbs.dbCount = 1;
  g_Dbs.db[0].drop = 1;
6818

6819
  tstrncpy(g_Dbs.db[0].dbName, g_args.database, MAX_DB_NAME_SIZE);
6820
  g_Dbs.db[0].dbCfg.replica = g_args.replica;
6821
  tstrncpy(g_Dbs.db[0].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
L
Liu Tao 已提交
6822

6823
  tstrncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN);
6824 6825 6826 6827 6828

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

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

6830 6831
  char dataString[STRING_LEN];
  char **data_type = g_args.datatype;
6832

6833
  memset(dataString, 0, STRING_LEN);
L
Liu Tao 已提交
6834

6835 6836
  if (strcasecmp(data_type[0], "BINARY") == 0
          || strcasecmp(data_type[0], "BOOL") == 0
6837
          || strcasecmp(data_type[0], "NCHAR") == 0 ) {
6838
    g_Dbs.do_aggreFunc = false;
L
Liu Tao 已提交
6839
  }
H
hzcheng 已提交
6840

6841 6842 6843 6844 6845
  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;
6846
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
6847
    g_Dbs.queryMode = g_args.query_mode;
6848

6849 6850 6851 6852
    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;
6853
    tstrncpy(g_Dbs.db[0].superTbls[0].childTblPrefix,
6854 6855 6856
            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);
6857
    tstrncpy(g_Dbs.db[0].superTbls[0].startTimestamp,
6858
            "2017-07-14 10:40:00.000", MAX_TB_NAME_SIZE);
6859
    g_Dbs.db[0].superTbls[0].timeStampStep = DEFAULT_TIMESTAMP_STEP;
6860

6861
    g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT;
6862
    g_Dbs.db[0].superTbls[0].maxSqlLen = g_args.max_sql_len;
6863

6864 6865 6866 6867 6868
    g_Dbs.db[0].superTbls[0].columnCount = 0;
    for (int i = 0; i < MAX_NUM_DATATYPE; i++) {
      if (data_type[i] == NULL) {
        break;
      }
6869

6870
      tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
6871
              data_type[i], MAX_TB_NAME_SIZE);
6872
      g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary;
6873 6874
      g_Dbs.db[0].superTbls[0].columnCount++;
    }
6875

6876 6877 6878 6879 6880
    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);
6881
        g_Dbs.db[0].superTbls[0].columns[i].dataLen = 0;
6882 6883 6884
        g_Dbs.db[0].superTbls[0].columnCount++;
      }
    }
6885

6886
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType, "INT", MAX_TB_NAME_SIZE);
6887
    g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0;
6888

6889
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType, "BINARY", MAX_TB_NAME_SIZE);
6890 6891
    g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary;
    g_Dbs.db[0].superTbls[0].tagCount = 2;
6892
  } else {
6893 6894
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
    g_Dbs.db[0].superTbls[0].tagCount = 0;
H
hzcheng 已提交
6895
  }
6896 6897 6898 6899 6900 6901
}

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

6903 6904 6905
  /* Compile regular expression */
  if (regcomp(&regex, reg, cflags) != 0) {
    printf("Fail to compile regex\n");
H
Hui Li 已提交
6906 6907 6908
    exit(-1);
  }

6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932
  /* 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);
}

6933
static void querySqlFile(TAOS* taos, char* sqlFile)
6934 6935 6936 6937 6938 6939
{
  FILE *fp = fopen(sqlFile, "r");
  if (fp == NULL) {
    printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno));
    return;
  }
6940

6941 6942 6943 6944 6945 6946
  int       read_len = 0;
  char *    cmd = calloc(1, MAX_SQL_SIZE);
  size_t    cmd_len = 0;
  char *    line = NULL;
  size_t    line_len = 0;

6947
  double t = taosGetTimestampMs();
6948

6949
  while((read_len = tgetline(&line, &line_len, fp)) != -1) {
6950 6951 6952 6953 6954 6955 6956 6957 6958 6959 6960 6961
    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;
6962
    }
6963 6964

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

6978
  t = taosGetTimestampMs() - t;
6979
  printf("run %s took %.6f second(s)\n\n", sqlFile, t);
6980

6981 6982 6983 6984
  tmfree(cmd);
  tmfree(line);
  tmfclose(fp);
  return;
H
hzcheng 已提交
6985 6986
}

6987
static void testMetaFile() {
6988
    if (INSERT_TEST == g_args.test_mode) {
6989 6990
      if (g_Dbs.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir);
6991

6992
      insertTestProcess();
6993

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

6998
      queryTestProcess();
6999

7000
    } else if (SUBSCRIBE_TEST == g_args.test_mode) {
7001 7002
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
7003

7004
      subscribeTestProcess();
7005

7006 7007 7008
    }  else {
      ;
    }
7009
}
7010

7011
static void queryResult() {
7012
  // query data
7013

7014 7015 7016 7017 7018
  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;
7019

7020 7021 7022 7023 7024 7025 7026 7027 7028 7029 7030 7031 7032 7033 7034 7035 7036 7037 7038 7039 7040 7041 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055
  //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);
7056 7057
}

7058 7059
static void testCmdLine() {

7060 7061 7062 7063 7064 7065 7066 7067 7068 7069
  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);
  }

7070 7071
  g_args.test_mode = INSERT_TEST;
  insertTestProcess();
7072

7073
  if (false == g_Dbs.insert_only)
7074
    queryResult();
7075 7076
}

7077 7078 7079
int main(int argc, char *argv[]) {
  parse_args(argc, argv, &g_args);

7080
  debugPrint("meta file: %s\n", g_args.metaFile);
7081 7082 7083

  if (g_args.metaFile) {
    initOfInsertMeta();
7084
    initOfQueryMeta();
7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097

    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(
7098 7099 7100 7101
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
7102
          g_Dbs.port);
7103
      querySqlFile(qtaos, g_args.sqlFile);
7104 7105 7106 7107 7108
      taos_close(qtaos);

    } else {
      testCmdLine();
    }
H
hzcheng 已提交
7109
  }
7110 7111

  return 0;
H
hzcheng 已提交
7112
}
7113