taosdemo.c 34.7 KB
Newer Older
H
hzcheng 已提交
1 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/>.
 */

S
slguan 已提交
16
#define _GNU_SOURCE
H
hzcheng 已提交
17 18 19

#include <argp.h>
#include <assert.h>
L
lihui 已提交
20
#include <inttypes.h>
S
#1022  
slguan 已提交
21 22

#ifndef _ALPINE
H
hzcheng 已提交
23
#include <error.h>
F
Frozen 已提交
24
#endif
H
hzcheng 已提交
25 26 27 28 29 30 31 32 33 34 35 36
#include <pthread.h>
#include <semaphore.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <wordexp.h>

#include "taos.h"
H
Hui Li 已提交
37
#include "tutil.h"
S
slguan 已提交
38 39 40

extern char configDir[];

H
hzcheng 已提交
41 42 43 44 45 46
#define BUFFER_SIZE      65536
#define MAX_DB_NAME_SIZE 64
#define MAX_TB_NAME_SIZE 64
#define MAX_DATA_SIZE    1024
#define MAX_NUM_DATATYPE 8
#define OPT_ABORT        1 /* –abort */
47
#define STRING_LEN       512
H
hzcheng 已提交
48 49 50 51 52 53

/* The options we understand. */
static struct argp_option options[] = {
  {0, 'h', "host",                     0, "The host to connect to TDEngine. Default is localhost.",                                                           0},
  {0, 'p', "port",                     0, "The TCP/IP port number to use for the connection. Default is 0.",                                                  1},
  {0, 'u', "user",                     0, "The TDEngine user name to use when connecting to the server. Default is 'root'.",                                  2},
S
Shuaiqiang Chang 已提交
54 55
  {0, 'P', "password",                 0, "The password to use when connecting to the server. Default is 'taosdata'.",                                        3},
  {0, 'd', "database",                 0, "Destination database. Default is 'test'.",                                                                         3},
H
hzcheng 已提交
56 57 58 59 60 61
  {0, 'm', "table_prefix",             0, "Table prefix name. Default is 't'.",                                                                               3},
  {0, 'M', 0,                          0, "Use metric flag.",                                                                                                 13},
  {0, 'o', "outputfile",               0, "Direct output to the named file. Default is './output.txt'.",                                                      14},
  {0, 'q', "query_mode",               0, "Query mode--0: SYNC, 1: ASYNC. Default is SYNC.",                                                                  6},
  {0, 'b', "type_of_cols",             0, "The data_type of columns: 'INT', 'TINYINT', 'SMALLINT', 'BIGINT', 'FLOAT', 'DOUBLE', 'BINARY'. Default is 'INT'.", 7},
  {0, 'w', "length_of_binary",         0, "The length of data_type 'BINARY'. Only applicable when type of cols is 'BINARY'. Default is 8",                    8},
62
  {0, 'l', "num_of_cols_per_record",   0, "The number of columns per record. Default is 3.",                                                                  8},
S
Shuaiqiang Chang 已提交
63
  {0, 'T', "num_of_threads",           0, "The number of threads. Default is 10.",                                                                            9},
S
slguan 已提交
64 65 66
  {0, 'r', "num_of_records_per_req",   0, "The number of records per request. Default is 1000.",                                                              10},
  {0, 't', "num_of_tables",            0, "The number of tables. Default is 10000.",                                                                          11},
  {0, 'n', "num_of_records_per_table", 0, "The number of records per table. Default is 100000.",                                                              12},
S
Shuaiqiang Chang 已提交
67
  {0, 'c', "config_directory",         0, "Configuration directory. Default is '/etc/taos/'.",                                                                14},
H
hzcheng 已提交
68
  {0, 'x', 0,                          0, "Insert only flag.",                                                                                                13},
S
Shuaiqiang Chang 已提交
69 70 71
  {0, 'O', "order",                    0, "Insert mode--0: In order, 1: Out of order. Default is in order.",                                                  14},
  {0, 'R', "rate",                     0, "Out of order data's rate--if order=1 Default 10, min: 0, max: 50.",                                                14},
  {0, 'D', "delete table",             0, "Delete data methods——0: don't delete, 1: delete by table, 2: delete by stable, 3: delete by database",             14},
H
hzcheng 已提交
72 73 74
  {0}};

/* Used by main to communicate with parse_opt. */
75
typedef struct DemoArguments {
H
hzcheng 已提交
76
  char  *host;
L
lihui 已提交
77
  uint16_t    port;
H
hzcheng 已提交
78 79 80 81 82 83 84 85
  char  *user;
  char  *password;
  char  *database;
  char  *tb_prefix;
  bool   use_metric;
  bool   insert_only;
  char  *output_file;
  int    mode;
H
Hui Li 已提交
86
  char  *datatype[MAX_NUM_DATATYPE+1];
H
hzcheng 已提交
87 88
  int    len_of_binary;
  int    num_of_CPR;
S
Shuaiqiang Chang 已提交
89
  int    num_of_threads;
H
hzcheng 已提交
90 91 92 93
  int    num_of_RPR;
  int    num_of_tables;
  int    num_of_DPT;
  int    abort;
S
Shuaiqiang Chang 已提交
94 95
  int    order;
  int    rate;
S
Shuaiqiang Chang 已提交
96
  int    method_of_delete;
H
hzcheng 已提交
97
  char **arg_list;
98
} SDemoArguments;
H
hzcheng 已提交
99 100 101 102 103

/* Parse a single option. */
static error_t parse_opt(int key, char *arg, struct argp_state *state) {
  /* Get the input argument from argp_parse, which we
     know is a pointer to our arguments structure. */
104
  SDemoArguments *arguments = state->input;
H
hzcheng 已提交
105 106 107 108 109 110 111 112 113 114 115 116
  wordexp_t full_path;
  char **sptr;
  switch (key) {
    case 'h':
      arguments->host = arg;
      break;
    case 'p':
      arguments->port = atoi(arg);
      break;
    case 'u':
      arguments->user = arg;
      break;
S
Shuaiqiang Chang 已提交
117
    case 'P':
H
hzcheng 已提交
118 119 120 121 122 123 124 125
      arguments->password = arg;
      break;
    case 'o':
      arguments->output_file = arg;
      break;
    case 'q':
      arguments->mode = atoi(arg);
      break;
S
Shuaiqiang Chang 已提交
126 127
    case 'T':
      arguments->num_of_threads = atoi(arg);
H
hzcheng 已提交
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
      break;
    case 'r':
      arguments->num_of_RPR = atoi(arg);
      break;
    case 't':
      arguments->num_of_tables = atoi(arg);
      break;
    case 'n':
      arguments->num_of_DPT = atoi(arg);
      break;
    case 'd':
      arguments->database = arg;
      break;
    case 'l':
      arguments->num_of_CPR = atoi(arg);
      break;
    case 'b':
      sptr = arguments->datatype;
      if (strstr(arg, ",") == NULL) {
        if (strcasecmp(arg, "INT") != 0 && strcasecmp(arg, "FLOAT") != 0 &&
            strcasecmp(arg, "TINYINT") != 0 && strcasecmp(arg, "BOOL") != 0 &&
            strcasecmp(arg, "SMALLINT") != 0 &&
            strcasecmp(arg, "BIGINT") != 0 && strcasecmp(arg, "DOUBLE") != 0 &&
            strcasecmp(arg, "BINARY")) {
          argp_error(state, "Invalid data_type!");
        }
        sptr[0] = arg;
      } else {
        int index = 0;
        char *dupstr = strdup(arg);
        char *running = dupstr;
        char *token = strsep(&running, ",");
        while (token != NULL) {
          if (strcasecmp(token, "INT") != 0 &&
              strcasecmp(token, "FLOAT") != 0 &&
              strcasecmp(token, "TINYINT") != 0 &&
              strcasecmp(token, "BOOL") != 0 &&
              strcasecmp(token, "SMALLINT") != 0 &&
              strcasecmp(token, "BIGINT") != 0 &&
              strcasecmp(token, "DOUBLE") != 0 && strcasecmp(token, "BINARY")) {
            argp_error(state, "Invalid data_type!");
          }
          sptr[index++] = token;
          token = strsep(&running, ", ");
        }
      }
      break;
    case 'w':
      arguments->len_of_binary = atoi(arg);
      break;
    case 'm':
      arguments->tb_prefix = arg;
      break;
    case 'M':
      arguments->use_metric = true;
      break;
    case 'x':
      arguments->insert_only = true;
      break;
S
Shuaiqiang Chang 已提交
187
    case 'c':
H
hzcheng 已提交
188 189 190 191
      if (wordexp(arg, &full_path, 0) != 0) {
        fprintf(stderr, "Invalid path %s\n", arg);
        return -1;
      }
192
      taos_options(TSDB_OPTION_CONFIGDIR, full_path.we_wordv[0]);
H
hzcheng 已提交
193 194
      wordfree(&full_path);
      break;
S
Shuaiqiang Chang 已提交
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
    case 'O':
      arguments->order = atoi(arg);
      if (arguments->order > 1 || arguments->order < 0)
      {
        arguments->order = 0;
      } else if (arguments->order == 1)
      {
        arguments->rate = 10;
      }
      break;
    case 'R':
      arguments->rate = atoi(arg);
      if (arguments->order == 1 && (arguments->rate > 50 || arguments->rate <= 0))
      {
        arguments->rate = 10;
      }
      break;
S
Shuaiqiang Chang 已提交
212 213 214 215 216 217 218
    case 'D':
      arguments->method_of_delete = atoi(arg);
      if (arguments->method_of_delete < 0 || arguments->method_of_delete > 3)
      {
        arguments->method_of_delete = 0;
      }
      break;
H
hzcheng 已提交
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
    case OPT_ABORT:
      arguments->abort = 1;
      break;
    case ARGP_KEY_ARG:
      /*arguments->arg_list = &state->argv[state->next-1];
      state->next = state->argc;*/
      argp_usage(state);
      break;

    default:
      return ARGP_ERR_UNKNOWN;
  }
  return 0;
}

/* ******************************* Structure
 * definition*******************************  */
enum MODE {
  SYNC, ASYNC
};
typedef struct {
  TAOS *taos;
  int threadID;
  char db_name[MAX_DB_NAME_SIZE];
  char fp[4096];
  char **datatype;
  int len_of_binary;
  char tb_prefix[MAX_TB_NAME_SIZE];
  int start_table_id;
  int end_table_id;
  int ncols_per_record;
  int nrecords_per_table;
  int nrecords_per_request;
S
Shuaiqiang Chang 已提交
252 253
  int data_of_order;
  int data_of_rate;
S
slguan 已提交
254
  int64_t start_time;
H
hzcheng 已提交
255 256 257 258 259 260 261 262 263 264 265
  bool do_aggreFunc;

  sem_t mutex_sem;
  int notFinished;
  sem_t lock_sem;
} info;

typedef struct {
  TAOS  *taos;

  char   tb_name[MAX_TB_NAME_SIZE];
S
slguan 已提交
266
  int64_t   timestamp;
H
hzcheng 已提交
267 268 269 270 271 272
  int    target;
  int    counter;
  int    nrecords_per_request;
  int    ncols_per_record;
  char **data_type;
  int    len_of_binary;
S
Shuaiqiang Chang 已提交
273 274
  int data_of_order;
  int data_of_rate;
H
hzcheng 已提交
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296

  sem_t *mutex_sem;
  int   *notFinished;
  sem_t *lock_sem;
} sTable;

/* ******************************* Global
 * variables*******************************  */
char *aggreFunc[] = {"*", "count(*)", "avg(f1)", "sum(f1)", "max(f1)", "min(f1)", "first(f1)", "last(f1)"};

/* ******************************* Global
 * functions*******************************  */
static struct argp argp = {options, parse_opt, 0, 0};

void queryDB(TAOS *taos, char *command);

void *readTable(void *sarg);

void *readMetric(void *sarg);

void *syncWrite(void *sarg);

S
Shuaiqiang Chang 已提交
297 298
void *deleteTable();

H
hzcheng 已提交
299 300
void *asyncWrite(void *sarg);

301
int generateData(char *res, char **data_type, int num_of_cols, int64_t timestamp, int len_of_binary);
H
hzcheng 已提交
302 303 304 305 306 307 308 309

void rand_string(char *str, int size);

double getCurrentTime();

void callBack(void *param, TAOS_RES *res, int code);

int main(int argc, char *argv[]) {
310
  SDemoArguments arguments = {  NULL,            // host
H
Hongze Cheng 已提交
311 312 313 314 315 316 317 318 319 320 321
                                0,               // port
                                "root",          // user
                                "taosdata",      // password
                                "test",          // database
                                "t",             // tb_prefix
                                false,           // use_metric
                                false,           // insert_only
                                "./output.txt",  // output_file
                                0,               // mode
                                {
                                "int",           // datatype
H
hzcheng 已提交
322 323 324 325 326 327
                                "",
                                "",
                                "",
                                "",
                                "",
                                "",
H
Hongze Cheng 已提交
328 329 330 331
                                ""
                                },
                                8,               // len_of_binary
                                1,               // num_of_CPR
S
Shuaiqiang Chang 已提交
332
                                1,               // num_of_connections/thread
H
Hongze Cheng 已提交
333 334 335 336
                                1,               // num_of_RPR
                                1,               // num_of_tables
                                50000,           // num_of_DPT
                                0,               // abort
S
Shuaiqiang Chang 已提交
337 338
                                0,               // order
                                0,               // rate
S
Shuaiqiang Chang 已提交
339
                                0,               // method_of_delete
H
Hongze Cheng 已提交
340 341
                                NULL             // arg_list
                                };
H
hzcheng 已提交
342 343 344

  /* Parse our arguments; every option seen by parse_opt will be
     reflected in arguments. */
345
  // For demo use, change default values for some parameters;
346
  arguments.num_of_tables = 10000;
347
  arguments.num_of_CPR = 3; 
S
Shuaiqiang Chang 已提交
348
  arguments.num_of_threads = 10;
349 350
  arguments.num_of_DPT = 100000;
  arguments.num_of_RPR = 1000;
351 352
  arguments.use_metric = true;
  arguments.insert_only = true;
S
slguan 已提交
353
  // end change
354

H
hzcheng 已提交
355 356
  argp_parse(&argp, argc, argv, 0, 0, &arguments);

F
Frozen 已提交
357
  if (arguments.abort) {
S
#1022  
slguan 已提交
358
    #ifndef _ALPINE
F
Frozen 已提交
359 360 361 362 363
      error(10, 0, "ABORTED");
    #else
      abort();
    #endif
  }
364
  
H
hzcheng 已提交
365 366
  enum MODE query_mode = arguments.mode;
  char *ip_addr = arguments.host;
L
lihui 已提交
367
  uint16_t port = arguments.port;
H
hzcheng 已提交
368 369 370 371 372 373
  char *user = arguments.user;
  char *pass = arguments.password;
  char *db_name = arguments.database;
  char *tb_prefix = arguments.tb_prefix;
  int len_of_binary = arguments.len_of_binary;
  int ncols_per_record = arguments.num_of_CPR;
S
Shuaiqiang Chang 已提交
374 375
  int order = arguments.order;
  int rate = arguments.rate;
S
Shuaiqiang Chang 已提交
376
  int method_of_delete = arguments.method_of_delete;
H
hzcheng 已提交
377
  int ntables = arguments.num_of_tables;
S
Shuaiqiang Chang 已提交
378
  int threads = arguments.num_of_threads;
H
hzcheng 已提交
379 380 381 382 383 384
  int nrecords_per_table = arguments.num_of_DPT;
  int nrecords_per_request = arguments.num_of_RPR;
  bool use_metric = arguments.use_metric;
  bool insert_only = arguments.insert_only;
  char **data_type = arguments.datatype;
  int count_data_type = 0;
385
  char dataString[STRING_LEN];
H
hzcheng 已提交
386
  bool do_aggreFunc = true;
387

388 389
  memset(dataString, 0, STRING_LEN);
  int len = 0;
390

H
hzcheng 已提交
391 392 393 394 395 396 397
  if (strcasecmp(data_type[0], "BINARY") == 0 || strcasecmp(data_type[0], "BOOL") == 0) {
    do_aggreFunc = false;
  }
  for (; count_data_type <= MAX_NUM_DATATYPE; count_data_type++) {
    if (strcasecmp(data_type[count_data_type], "") == 0) {
      break;
    }
398 399

    len += snprintf(dataString + len, STRING_LEN - len, "%s ", data_type[count_data_type]);
H
hzcheng 已提交
400 401 402
  }

  FILE *fp = fopen(arguments.output_file, "a");
403 404 405 406 407
  if (NULL == fp) {
    fprintf(stderr, "Failed to open %s for writing\n", arguments.output_file);
    return 1;
  };
  
H
hzcheng 已提交
408 409
  time_t tTime = time(NULL);
  struct tm tm = *localtime(&tTime);
S
Shuaiqiang Chang 已提交
410 411 412 413 414 415 416 417 418
  printf("###################################################################\n");
  printf("# Server IP:                         %s:%hu\n", ip_addr == NULL ? "localhost" : ip_addr, port);
  printf("# User:                              %s\n", user);
  printf("# Password:                          %s\n", pass);
  printf("# Use metric:                        %s\n", use_metric ? "true" : "false");
  printf("# Datatype of Columns:               %s\n", dataString);
  printf("# Binary Length(If applicable):      %d\n",
          (strcasestr(dataString, "BINARY") != NULL) ? len_of_binary : -1);
  printf("# Number of Columns per record:      %d\n", ncols_per_record);
S
Shuaiqiang Chang 已提交
419
  printf("# Number of Threads:                 %d\n", threads);
S
Shuaiqiang Chang 已提交
420 421 422 423 424
  printf("# Number of Tables:                  %d\n", ntables);
  printf("# Number of Data per Table:          %d\n", nrecords_per_table);
  printf("# Records/Request:                   %d\n", nrecords_per_request);
  printf("# Database name:                     %s\n", db_name);
  printf("# Table prefix:                      %s\n", tb_prefix);
S
Shuaiqiang Chang 已提交
425 426
  if (order == 1)
  {
S
Shuaiqiang Chang 已提交
427 428
    printf("# Data order:                        %d\n", order);
    printf("# Data out of order rate:            %d\n", rate);
S
Shuaiqiang Chang 已提交
429 430

  }
S
Shuaiqiang Chang 已提交
431
  printf("# Delete method:                     %d\n", method_of_delete);
S
Shuaiqiang Chang 已提交
432 433 434 435
  printf("# Test time:                         %d-%02d-%02d %02d:%02d:%02d\n", tm.tm_year + 1900, tm.tm_mon + 1,
          tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
  printf("###################################################################\n\n");
  printf("Press enter key to continue");
H
Hui Li 已提交
436
  (void)getchar();
H
hzcheng 已提交
437 438

  fprintf(fp, "###################################################################\n");
L
lihui 已提交
439
  fprintf(fp, "# Server IP:                         %s:%hu\n", ip_addr == NULL ? "localhost" : ip_addr, port);
H
hzcheng 已提交
440 441 442 443 444 445 446
  fprintf(fp, "# User:                              %s\n", user);
  fprintf(fp, "# Password:                          %s\n", pass);
  fprintf(fp, "# Use metric:                        %s\n", use_metric ? "true" : "false");
  fprintf(fp, "# Datatype of Columns:               %s\n", dataString);
  fprintf(fp, "# Binary Length(If applicable):      %d\n",
          (strcasestr(dataString, "BINARY") != NULL) ? len_of_binary : -1);
  fprintf(fp, "# Number of Columns per record:      %d\n", ncols_per_record);
S
Shuaiqiang Chang 已提交
447
  fprintf(fp, "# Number of Threads:                 %d\n", threads);
H
hzcheng 已提交
448 449 450 451 452
  fprintf(fp, "# Number of Tables:                  %d\n", ntables);
  fprintf(fp, "# Number of Data per Table:          %d\n", nrecords_per_table);
  fprintf(fp, "# Records/Request:                   %d\n", nrecords_per_request);
  fprintf(fp, "# Database name:                     %s\n", db_name);
  fprintf(fp, "# Table prefix:                      %s\n", tb_prefix);
S
Shuaiqiang Chang 已提交
453 454 455 456 457 458
  if (order == 1)
  {
    printf("# Data order:                        %d\n", order);
    printf("# Data out of order rate:            %d\n", rate);

  }
H
hzcheng 已提交
459 460 461 462 463 464 465 466
  fprintf(fp, "# Test time:                         %d-%02d-%02d %02d:%02d:%02d\n", tm.tm_year + 1900, tm.tm_mon + 1,
          tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
  fprintf(fp, "###################################################################\n\n");
  fprintf(fp, "|  WRecords  | Records/Second | Requests/Second |  WLatency(ms) |\n");

  taos_init();
  TAOS *taos = taos_connect(ip_addr, user, pass, NULL, port);
  if (taos == NULL) {
S
Shuaiqiang Chang 已提交
467
    fprintf(stderr, "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL));
H
hzcheng 已提交
468 469 470 471 472
    return 1;
  }
  char command[BUFFER_SIZE] = "\0";

  sprintf(command, "drop database %s;", db_name);
473 474
  TAOS_RES* res = taos_query(taos, command);
  taos_free_result(res);
H
hzcheng 已提交
475 476

  sprintf(command, "create database %s;", db_name);
477 478
  res = taos_query(taos, command);
  taos_free_result(res);
H
hzcheng 已提交
479

480
  char cols[STRING_LEN] = "\0";
H
hzcheng 已提交
481
  int colIndex = 0;
482
  len = 0;
H
hzcheng 已提交
483 484 485

  for (; colIndex < ncols_per_record - 1; colIndex++) {
    if (strcasecmp(data_type[colIndex % count_data_type], "BINARY") != 0) {
486
      len += snprintf(cols + len, STRING_LEN - len, ",f%d %s", colIndex + 1, data_type[colIndex % count_data_type]);
H
hzcheng 已提交
487
    } else {
488
      len += snprintf(cols + len, STRING_LEN - len, ",f%d %s(%d)", colIndex + 1, data_type[colIndex % count_data_type], len_of_binary);
H
hzcheng 已提交
489 490 491 492
    }
  }

  if (strcasecmp(data_type[colIndex % count_data_type], "BINARY") != 0) {
493
    len += snprintf(cols + len, STRING_LEN - len, ",f%d %s)", colIndex + 1, data_type[colIndex % count_data_type]);
H
hzcheng 已提交
494
  } else {
495
    len += snprintf(cols + len, STRING_LEN - len, ",f%d %s(%d))", colIndex + 1, data_type[colIndex % count_data_type], len_of_binary);
H
hzcheng 已提交
496 497 498 499 500 501
  }

  if (!use_metric) {
    /* Create all the tables; */
    printf("Creating %d table(s)......\n", ntables);
    for (int i = 0; i < ntables; i++) {
502
      snprintf(command, BUFFER_SIZE, "create table if not exists %s.%s%d (ts timestamp%s;", db_name, tb_prefix, i, cols);
H
hzcheng 已提交
503 504 505 506 507 508 509 510
      queryDB(taos, command);
    }

    printf("Table(s) created!\n");
    taos_close(taos);

  } else {
    /* Create metric table */
511
    printf("Creating meters super table...\n");
512
    snprintf(command, BUFFER_SIZE, "create table if not exists %s.meters (ts timestamp%s tags (areaid int, loc binary(10))", db_name, cols);
H
hzcheng 已提交
513
    queryDB(taos, command);
514
    printf("meters created!\n");
H
hzcheng 已提交
515 516 517 518 519 520 521 522 523 524

    /* Create all the tables; */
    printf("Creating %d table(s)......\n", ntables);
    for (int i = 0; i < ntables; i++) {
      int j;
      if (i % 10 == 0) {
        j = 10;
      } else {
        j = i % 10;
      }
525
    if (j % 2 == 0) {
526
      snprintf(command, BUFFER_SIZE, "create table if not exists %s.%s%d using %s.meters tags (%d,\"%s\");", db_name, tb_prefix, i, db_name, j, "shanghai");
527
    } else {
528
      snprintf(command, BUFFER_SIZE, "create table if not exists %s.%s%d using %s.meters tags (%d,\"%s\");", db_name, tb_prefix, i, db_name, j, "beijing");
529
    }
H
hzcheng 已提交
530 531 532 533 534 535 536
      queryDB(taos, command);
    }

    printf("Table(s) created!\n");
    taos_close(taos);
  }
  /* Wait for table to create  */
S
Shuaiqiang Chang 已提交
537
  
H
hzcheng 已提交
538 539 540 541

  /* Insert data */
  double ts = getCurrentTime();
  printf("Inserting data......\n");
S
Shuaiqiang Chang 已提交
542 543
  pthread_t *pids = malloc(threads * sizeof(pthread_t));
  info *infos = malloc(threads * sizeof(info));
H
hzcheng 已提交
544

S
Shuaiqiang Chang 已提交
545
  int a = ntables / threads;
H
hzcheng 已提交
546
  if (a < 1) {
S
Shuaiqiang Chang 已提交
547
    threads = ntables;
H
hzcheng 已提交
548 549
    a = 1;
  }
S
Shuduo Sang 已提交
550 551 552 553

  int b = 0;
  if (threads != 0)
    b = ntables % threads;
H
hzcheng 已提交
554
  int last = 0;
S
Shuaiqiang Chang 已提交
555
  for (int i = 0; i < threads; i++) {
H
hzcheng 已提交
556 557
    info *t_info = infos + i;
    t_info->threadID = i;
H
Hui Li 已提交
558 559
    tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE);
    tstrncpy(t_info->tb_prefix, tb_prefix, MAX_TB_NAME_SIZE);
H
hzcheng 已提交
560 561 562 563 564 565 566 567
    t_info->datatype = data_type;
    t_info->ncols_per_record = ncols_per_record;
    t_info->nrecords_per_table = nrecords_per_table;
    t_info->start_time = 1500000000000;
    t_info->taos = taos_connect(ip_addr, user, pass, db_name, port);
    t_info->len_of_binary = len_of_binary;
    t_info->nrecords_per_request = nrecords_per_request;
    t_info->start_table_id = last;
S
Shuaiqiang Chang 已提交
568 569
    t_info->data_of_order = order;
    t_info->data_of_rate = rate;
H
hzcheng 已提交
570 571 572 573 574 575 576 577 578 579 580 581 582
    t_info->end_table_id = i < b ? last + a : last + a - 1;
    last = t_info->end_table_id + 1;

    sem_init(&(t_info->mutex_sem), 0, 1);
    t_info->notFinished = t_info->end_table_id - t_info->start_table_id + 1;
    sem_init(&(t_info->lock_sem), 0, 0);

    if (query_mode == SYNC) {
      pthread_create(pids + i, NULL, syncWrite, t_info);
    } else {
      pthread_create(pids + i, NULL, asyncWrite, t_info);
    }
  }
S
Shuaiqiang Chang 已提交
583
  for (int i = 0; i < threads; i++) {
H
hzcheng 已提交
584 585 586 587 588
    pthread_join(pids[i], NULL);
  }

  double t = getCurrentTime() - ts;
  if (query_mode == SYNC) {
S
Shuaiqiang Chang 已提交
589
    printf("SYNC Insert with %d connections:\n", threads);
H
hzcheng 已提交
590
  } else {
S
Shuaiqiang Chang 已提交
591
    printf("ASYNC Insert with %d connections:\n", threads);
H
hzcheng 已提交
592 593 594 595 596 597 598 599 600 601 602
  }

  fprintf(fp, "|%10.d  |  %10.2f    |  %10.2f     |  %10.4f   |\n\n",
          ntables * nrecords_per_table, ntables * nrecords_per_table / t,
          (ntables * nrecords_per_table) / (t * nrecords_per_request),
          t * 1000);

  printf("Spent %.4f seconds to insert %d records with %d record(s) per request: %.2f records/second\n",
         t, ntables * nrecords_per_table, nrecords_per_request,
         ntables * nrecords_per_table / t);

S
Shuaiqiang Chang 已提交
603
  for (int i = 0; i < threads; i++) {
H
hzcheng 已提交
604 605 606 607 608 609 610 611 612 613
    info *t_info = infos + i;
    taos_close(t_info->taos);
    sem_destroy(&(t_info->mutex_sem));
    sem_destroy(&(t_info->lock_sem));
  }

  free(pids);
  free(infos);
  fclose(fp);

S
Shuaiqiang Chang 已提交
614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662
  if (method_of_delete != 0)
  {
    TAOS *dtaos = taos_connect(ip_addr, user, pass, db_name, port);
    double dts = getCurrentTime();
    printf("Deleteing %d table(s)......\n", ntables);

    switch (method_of_delete)
    {
    case 1:
      // delete by table
      /* Create all the tables; */
      for (int i = 0; i < ntables; i++) {
        sprintf(command, "drop table %s.%s%d;", db_name, tb_prefix, i);
        queryDB(dtaos, command);
      }
      break;
    case 2:
      // delete by stable
      if (!use_metric) {
        break;
      }
      else
      {
        sprintf(command, "drop table %s.meters;", db_name);
        queryDB(dtaos, command);
      }
      break;
    case 3:
      // delete by database
      sprintf(command, "drop database %s;", db_name);
      queryDB(dtaos, command);
      break;
    default:
      break;
    }

    printf("Table(s) droped!\n");
    taos_close(dtaos);

    double dt = getCurrentTime() - dts;
    printf("Spent %.4f seconds to drop %d tables\n", dt, ntables);

    FILE *fp = fopen(arguments.output_file, "a");
    fprintf(fp, "Spent %.4f seconds to drop %d tables\n", dt, ntables);
    fclose(fp);

  }
  

H
hzcheng 已提交
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
  if (!insert_only) {
    // query data
    pthread_t read_id;
    info *rInfo = malloc(sizeof(info));
    rInfo->start_time = 1500000000000;
    rInfo->start_table_id = 0;
    rInfo->end_table_id = ntables - 1;
    rInfo->do_aggreFunc = do_aggreFunc;
    rInfo->nrecords_per_table = nrecords_per_table;
    rInfo->taos = taos_connect(ip_addr, user, pass, db_name, port);
    strcpy(rInfo->tb_prefix, tb_prefix);
    strcpy(rInfo->fp, arguments.output_file);

    if (!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);
  }

  return 0;
}

void *readTable(void *sarg) {
  info *rinfo = (info *)sarg;
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
S
slguan 已提交
692
  int64_t sTime = rinfo->start_time;
H
hzcheng 已提交
693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710
  char *tb_prefix = rinfo->tb_prefix;
  FILE *fp = fopen(rinfo->fp, "a");
  int num_of_DPT = rinfo->nrecords_per_table;
  int num_of_tables = rinfo->end_table_id - rinfo->start_table_id + 1;
  int totalData = num_of_DPT * num_of_tables;
  bool do_aggreFunc = rinfo->do_aggreFunc;

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

  for (int j = 0; j < n; j++) {
    double totalT = 0;
    int count = 0;
    for (int i = 0; i < num_of_tables; i++) {
L
lihui 已提交
711
      sprintf(command, "select %s from %s%d where ts>= %" PRId64, aggreFunc[j], tb_prefix, i, sTime);
H
hzcheng 已提交
712 713

      double t = getCurrentTime();
S
Shuaiqiang Chang 已提交
714 715
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);
H
hzcheng 已提交
716

S
Shuaiqiang Chang 已提交
717
      if (code != 0) {
H
Haojun Liao 已提交
718
        fprintf(stderr, "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
719
        taos_free_result(pSql);
H
hzcheng 已提交
720
        taos_close(taos);
S
Shuaiqiang Chang 已提交
721
        exit(EXIT_FAILURE);
H
hzcheng 已提交
722 723
      }

S
Shuaiqiang Chang 已提交
724
      while (taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
725 726 727 728 729 730
        count++;
      }

      t = getCurrentTime() - t;
      totalT += t;

S
Shuaiqiang Chang 已提交
731
      taos_free_result(pSql);
H
hzcheng 已提交
732 733 734
    }

    fprintf(fp, "|%10s  |   %10d   |  %12.2f   |   %10.2f  |\n",
S
slguan 已提交
735
            aggreFunc[j][0] == '*' ? "   *   " : aggreFunc[j], totalData,
H
hzcheng 已提交
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
            (double)(num_of_tables * num_of_DPT) / totalT, totalT * 1000);
    printf("select %10s took %.6f second(s)\n", aggreFunc[j], totalT);
  }
  fprintf(fp, "\n");

  fclose(fp);
  return NULL;
}

void *readMetric(void *sarg) {
  info *rinfo = (info *)sarg;
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
  FILE *fp = fopen(rinfo->fp, "a");
  int num_of_DPT = rinfo->nrecords_per_table;
  int num_of_tables = rinfo->end_table_id - rinfo->start_table_id + 1;
  int totalData = num_of_DPT * num_of_tables;
  bool do_aggreFunc = rinfo->do_aggreFunc;

  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 已提交
763
    char condition[BUFFER_SIZE - 30] = "\0";
B
Bomin Zhang 已提交
764
    char tempS[64] = "\0";
H
hzcheng 已提交
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782

    int m = 10 < num_of_tables ? 10 : num_of_tables;

    for (int i = 1; i <= m; i++) {
      if (i == 1) {
        sprintf(tempS, "index = %d", i);
      } else {
        sprintf(tempS, " or index = %d ", i);
      }
      strcat(condition, tempS);

      sprintf(command, "select %s from m1 where %s", aggreFunc[j], condition);

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

      double t = getCurrentTime();

S
Shuaiqiang Chang 已提交
783 784 785 786
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);

      if (code != 0) {
H
Haojun Liao 已提交
787
        fprintf(stderr, "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
788
        taos_free_result(pSql);
H
hzcheng 已提交
789 790 791 792
        taos_close(taos);
        exit(1);
      }
      int count = 0;
S
Shuaiqiang Chang 已提交
793
      while (taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
794 795 796 797 798 799 800
        count++;
      }
      t = getCurrentTime() - t;

      fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n", num_of_tables * num_of_DPT / t, t * 1000);
      printf("select %10s took %.6f second(s)\n\n", aggreFunc[j], t);

S
Shuaiqiang Chang 已提交
801
      taos_free_result(pSql);
H
hzcheng 已提交
802 803 804 805 806 807 808 809 810
    }
    fprintf(fp, "\n");
  }

  fclose(fp);
  return NULL;
}

void queryDB(TAOS *taos, char *command) {
H
Hui Li 已提交
811
  int i;
S
Shuaiqiang Chang 已提交
812
  TAOS_RES *pSql = NULL;
H
Hui Li 已提交
813 814 815 816 817 818 819 820
  int32_t   code = -1;

  for (i = 0; i < 5; i++) {
    if (NULL != pSql) {
      taos_free_result(pSql);
      pSql = NULL;
    }
    
S
Shuaiqiang Chang 已提交
821 822
    pSql = taos_query(taos, command);
    code = taos_errno(pSql);
H
Hui Li 已提交
823
    if (0 == code) {
S
Shuaiqiang Chang 已提交
824
      break;
H
Hui Li 已提交
825
    }    
826
  }
S
Shuaiqiang Chang 已提交
827

dengyihao's avatar
dengyihao 已提交
828
  if (code != 0) {
H
Haojun Liao 已提交
829 830
    fprintf(stderr, "Failed to run %s, reason: %s\n", command, taos_errstr(pSql));
    taos_free_result(pSql);
H
hzcheng 已提交
831 832 833
    taos_close(taos);
    exit(EXIT_FAILURE);
  }
H
Hui Li 已提交
834 835

  taos_free_result(pSql);
H
hzcheng 已提交
836 837 838 839 840 841 842 843 844 845 846
}

// sync insertion
void *syncWrite(void *sarg) {
  info *winfo = (info *)sarg;
  char buffer[BUFFER_SIZE] = "\0";
  char data[MAX_DATA_SIZE];
  char **data_type = winfo->datatype;
  int len_of_binary = winfo->len_of_binary;
  int ncols_per_record = winfo->ncols_per_record;
  srand(time(NULL));
S
slguan 已提交
847
  int64_t time_counter = winfo->start_time;
H
hzcheng 已提交
848 849 850
  for (int i = 0; i < winfo->nrecords_per_table;) {
    for (int tID = winfo->start_table_id; tID <= winfo->end_table_id; tID++) {
      int inserted = i;
S
slguan 已提交
851
      int64_t tmp_time = time_counter;
H
hzcheng 已提交
852 853 854 855 856

      char *pstr = buffer;
      pstr += sprintf(pstr, "insert into %s.%s%d values", winfo->db_name, winfo->tb_prefix, tID);
      int k;
      for (k = 0; k < winfo->nrecords_per_request;) {
857
        int rand_num = rand() % 100;
858 859
        int len = -1;
        if (winfo->data_of_order ==1 && rand_num < winfo->data_of_rate) {
860
          long d = tmp_time - rand() % 1000000 + rand_num;
861 862 863
          len = generateData(data, data_type, ncols_per_record, d, len_of_binary);
        } else {
          len = generateData(data, data_type, ncols_per_record, tmp_time += 1000, len_of_binary);
S
Shuaiqiang Chang 已提交
864
        }
865 866 867 868 869 870

        //assert(len + pstr - buffer < BUFFER_SIZE);
        if (len + pstr - buffer >= BUFFER_SIZE) { // too long
          break;
        }

H
hzcheng 已提交
871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908
        pstr += sprintf(pstr, " %s", data);
        inserted++;
        k++;

        if (inserted >= winfo->nrecords_per_table) break;
      }

      /* puts(buffer); */
      queryDB(winfo->taos, buffer);

      if (tID == winfo->end_table_id) {
        i = inserted;
        time_counter = tmp_time;
      }
    }
  }
  return NULL;
}

void *asyncWrite(void *sarg) {
  info *winfo = (info *)sarg;

  sTable *tb_infos = (sTable *)malloc(sizeof(sTable) * (winfo->end_table_id - winfo->start_table_id + 1));

  for (int tID = winfo->start_table_id; tID <= winfo->end_table_id; tID++) {
    sTable *tb_info = tb_infos + tID - winfo->start_table_id;
    tb_info->data_type = winfo->datatype;
    tb_info->ncols_per_record = winfo->ncols_per_record;
    tb_info->taos = winfo->taos;
    sprintf(tb_info->tb_name, "%s.%s%d", winfo->db_name, winfo->tb_prefix, tID);
    tb_info->timestamp = winfo->start_time;
    tb_info->counter = 0;
    tb_info->target = winfo->nrecords_per_table;
    tb_info->len_of_binary = winfo->len_of_binary;
    tb_info->nrecords_per_request = winfo->nrecords_per_request;
    tb_info->mutex_sem = &(winfo->mutex_sem);
    tb_info->notFinished = &(winfo->notFinished);
    tb_info->lock_sem = &(winfo->lock_sem);
S
Shuaiqiang Chang 已提交
909 910
    tb_info->data_of_order = winfo->data_of_order;
    tb_info->data_of_rate = winfo->data_of_rate;
H
hzcheng 已提交
911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929

    /* char buff[BUFFER_SIZE] = "\0"; */
    /* sprintf(buff, "insert into %s values (0, 0)", tb_info->tb_name); */
    /* queryDB(tb_info->taos,buff); */

    taos_query_a(winfo->taos, "show databases", callBack, tb_info);
  }

  sem_wait(&(winfo->lock_sem));
  free(tb_infos);

  return NULL;
}

void callBack(void *param, TAOS_RES *res, int code) {
  sTable *tb_info = (sTable *)param;
  char **datatype = tb_info->data_type;
  int ncols_per_record = tb_info->ncols_per_record;
  int len_of_binary = tb_info->len_of_binary;
S
slguan 已提交
930
  int64_t tmp_time = tb_info->timestamp;
H
hzcheng 已提交
931 932

  if (code < 0) {
H
Haojun Liao 已提交
933
    fprintf(stderr, "failed to insert data %d:reason; %s\n", code, taos_errstr(res));
H
hzcheng 已提交
934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951
    exit(EXIT_FAILURE);
  }

  // If finished;
  if (tb_info->counter >= tb_info->target) {
    sem_wait(tb_info->mutex_sem);
    (*(tb_info->notFinished))--;
    if (*(tb_info->notFinished) == 0) sem_post(tb_info->lock_sem);
    sem_post(tb_info->mutex_sem);
    return;
  }

  char buffer[BUFFER_SIZE] = "\0";
  char data[MAX_DATA_SIZE];
  char *pstr = buffer;
  pstr += sprintf(pstr, "insert into %s values", tb_info->tb_name);

  for (int i = 0; i < tb_info->nrecords_per_request; i++) {
952
    int rand_num = rand() % 100;
S
Shuaiqiang Chang 已提交
953 954
    if (tb_info->data_of_order ==1 && rand_num < tb_info->data_of_rate)
    {
955
      long d = tmp_time - rand() % 1000000 + rand_num;
S
Shuaiqiang Chang 已提交
956 957 958 959 960
      generateData(data, datatype, ncols_per_record, d, len_of_binary);
    } else 
    {
      generateData(data, datatype, ncols_per_record, tmp_time += 1000, len_of_binary);
    }
H
hzcheng 已提交
961 962 963 964 965 966 967
    pstr += sprintf(pstr, "%s", data);
    tb_info->counter++;

    if (tb_info->counter >= tb_info->target) {
      break;
    }
  }
S
Shuaiqiang Chang 已提交
968
   tb_info->timestamp = tmp_time;
H
hzcheng 已提交
969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984

  taos_query_a(tb_info->taos, buffer, callBack, tb_info);

  taos_free_result(res);
}

double getCurrentTime() {
  struct timeval tv;
  if (gettimeofday(&tv, NULL) != 0) {
    perror("Failed to get current time in ms");
    exit(EXIT_FAILURE);
  }

  return tv.tv_sec + tv.tv_usec / 1E6;
}

985
int32_t generateData(char *res, char **data_type, int num_of_cols, int64_t timestamp, int len_of_binary) {
H
hzcheng 已提交
986 987
  memset(res, 0, MAX_DATA_SIZE);
  char *pstr = res;
L
lihui 已提交
988
  pstr += sprintf(pstr, "(%" PRId64, timestamp);
H
hzcheng 已提交
989 990 991 992 993 994 995 996
  int c = 0;

  for (; c < MAX_NUM_DATATYPE; c++) {
    if (strcasecmp(data_type[c], "") == 0) {
      break;
    }
  }

H
Hui Li 已提交
997 998 999 1000 1001
  if (0 == c) {
    perror("data type error!");
    exit(-1);
  }

H
hzcheng 已提交
1002 1003
  for (int i = 0; i < num_of_cols; i++) {
    if (strcasecmp(data_type[i % c], "tinyint") == 0) {
1004
      pstr += sprintf(pstr, ", %d", (int)(rand() % 128));
H
hzcheng 已提交
1005
    } else if (strcasecmp(data_type[i % c], "smallint") == 0) {
1006
      pstr += sprintf(pstr, ", %d", (int)(rand() % 32767));
H
hzcheng 已提交
1007
    } else if (strcasecmp(data_type[i % c], "int") == 0) {
1008
      pstr += sprintf(pstr, ", %d", (int)(rand() % 10)); 
H
hzcheng 已提交
1009
    } else if (strcasecmp(data_type[i % c], "bigint") == 0) {
1010
      pstr += sprintf(pstr, ", %" PRId64, rand() % 2147483648);
H
hzcheng 已提交
1011
    } else if (strcasecmp(data_type[i % c], "float") == 0) {
1012
      pstr += sprintf(pstr, ", %10.4f", (float)(rand() / 1000.0));
H
hzcheng 已提交
1013
    } else if (strcasecmp(data_type[i % c], "double") == 0) {
1014
      double t = (double)(rand() / 1000000.0);
H
hzcheng 已提交
1015 1016
      pstr += sprintf(pstr, ", %20.8f", t);
    } else if (strcasecmp(data_type[i % c], "bool") == 0) {
1017
      bool b = rand() & 1;
H
hzcheng 已提交
1018 1019 1020 1021
      pstr += sprintf(pstr, ", %s", b ? "true" : "false");
    } else if (strcasecmp(data_type[i % c], "binary") == 0) {
      char s[len_of_binary];
      rand_string(s, len_of_binary);
F
fang 已提交
1022
      pstr += sprintf(pstr, ", \"%s\"", s);
H
hzcheng 已提交
1023
    }
1024 1025 1026 1027 1028

    if (pstr - res > MAX_DATA_SIZE) {
      perror("column length too long, abort");
      exit(-1);
    }
H
hzcheng 已提交
1029 1030 1031
  }

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

  return pstr - res;
H
hzcheng 已提交
1034 1035
}

S
Shuaiqiang Chang 已提交
1036
static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJK1234567890";
H
hzcheng 已提交
1037
void rand_string(char *str, int size) {
S
Shuaiqiang Chang 已提交
1038 1039
  str[0] = 0;
  if (size > 0) {
H
hzcheng 已提交
1040
    --size;
S
Shuaiqiang Chang 已提交
1041 1042
    int n;
    for (n = 0; n < size; n++) {
1043
      int key = rand() % (int)(sizeof charset - 1);
S
Shuaiqiang Chang 已提交
1044
      str[n] = charset[key];
H
hzcheng 已提交
1045
    }
S
Shuaiqiang Chang 已提交
1046
    str[n] = 0;
H
hzcheng 已提交
1047 1048
  }
}