tconfig.c 28.8 KB
Newer Older
S
Shengliang Guan 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * 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/>.
 */

#define _DEFAULT_SOURCE
S
Shengliang Guan 已提交
17 18
#include "tconfig.h"
#include "taoserror.h"
S
log  
Shengliang Guan 已提交
19
#include "tlog.h"
S
Shengliang Guan 已提交
20
#include "tutil.h"
wafwerar's avatar
wafwerar 已提交
21 22 23
#include "tenv.h"
#include "cJSON.h"
#include "tjson.h"
S
Shengliang Guan 已提交
24

S
Shengliang Guan 已提交
25
#define CFG_NAME_PRINT_LEN 24
S
Shengliang Guan 已提交
26 27 28 29 30
#define CFG_SRC_PRINT_LEN  12

int32_t cfgLoadFromCfgFile(SConfig *pConfig, const char *filepath);
int32_t cfgLoadFromEnvFile(SConfig *pConfig, const char *filepath);
int32_t cfgLoadFromEnvVar(SConfig *pConfig);
wafwerar's avatar
wafwerar 已提交
31
int32_t cfgLoadFromEnvCmd(SConfig *pConfig, const char **envCmd);
S
Shengliang Guan 已提交
32 33
int32_t cfgLoadFromApollUrl(SConfig *pConfig, const char *url);
int32_t cfgSetItem(SConfig *pConfig, const char *name, const char *value, ECfgSrcType stype);
S
Shengliang Guan 已提交
34

S
Shengliang Guan 已提交
35
SConfig *cfgInit() {
wafwerar's avatar
wafwerar 已提交
36
  SConfig *pCfg = taosMemoryCalloc(1, sizeof(SConfig));
S
Shengliang Guan 已提交
37
  if (pCfg == NULL) {
S
cfgtest  
Shengliang Guan 已提交
38 39 40 41
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return NULL;
  }

S
Shengliang Guan 已提交
42 43
  pCfg->array = taosArrayInit(32, sizeof(SConfigItem));
  if (pCfg->array == NULL) {
wafwerar's avatar
wafwerar 已提交
44
    taosMemoryFree(pCfg);
S
cfgtest  
Shengliang Guan 已提交
45 46 47 48
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return NULL;
  }

S
Shengliang Guan 已提交
49
  return pCfg;
S
Shengliang Guan 已提交
50 51
}

wafwerar's avatar
wafwerar 已提交
52
int32_t cfgLoad(SConfig *pCfg, ECfgSrcType cfgType, const void *sourceStr) {
S
Shengliang Guan 已提交
53
  switch (cfgType) {
S
config  
Shengliang Guan 已提交
54
    case CFG_STYPE_CFG_FILE:
S
Shengliang Guan 已提交
55
      return cfgLoadFromCfgFile(pCfg, sourceStr);
S
config  
Shengliang Guan 已提交
56
    case CFG_STYPE_ENV_FILE:
S
Shengliang Guan 已提交
57
      return cfgLoadFromEnvFile(pCfg, sourceStr);
S
config  
Shengliang Guan 已提交
58
    case CFG_STYPE_ENV_VAR:
S
Shengliang Guan 已提交
59
      return cfgLoadFromEnvVar(pCfg);
S
config  
Shengliang Guan 已提交
60
    case CFG_STYPE_APOLLO_URL:
S
Shengliang Guan 已提交
61
      return cfgLoadFromApollUrl(pCfg, sourceStr);
wafwerar's avatar
wafwerar 已提交
62 63
    case CFG_STYPE_ENV_CMD:
      return cfgLoadFromEnvCmd(pCfg, (const char **)sourceStr);
S
Shengliang Guan 已提交
64 65 66 67 68
    default:
      return -1;
  }
}

69
int32_t cfgLoadFromArray(SConfig *pCfg, SArray *pArgs) {
S
Shengliang Guan 已提交
70 71 72
  int32_t size = taosArrayGetSize(pArgs);
  for (int32_t i = 0; i < size; ++i) {
    SConfigPair *pPair = taosArrayGet(pArgs, i);
S
Shengliang Guan 已提交
73 74 75
    if (cfgSetItem(pCfg, pPair->name, pPair->value, CFG_STYPE_ARG_LIST) != 0) {
      return -1;
    }
S
Shengliang Guan 已提交
76
  }
S
Shengliang Guan 已提交
77 78

  return 0;
S
Shengliang Guan 已提交
79 80
}

S
tfs cfg  
Shengliang Guan 已提交
81 82 83
static void cfgFreeItem(SConfigItem *pItem) {
  if (pItem->dtype == CFG_DTYPE_STRING || pItem->dtype == CFG_DTYPE_DIR || pItem->dtype == CFG_DTYPE_LOCALE ||
      pItem->dtype == CFG_DTYPE_CHARSET || pItem->dtype == CFG_DTYPE_TIMEZONE) {
wafwerar's avatar
wafwerar 已提交
84
    taosMemoryFreeClear(pItem->str);
S
tfs cfg  
Shengliang Guan 已提交
85 86 87 88 89 90 91
  }
  if (pItem->array) {
    taosArrayDestroy(pItem->array);
    pItem->array = NULL;
  }
}

S
Shengliang Guan 已提交
92 93
void cfgCleanup(SConfig *pCfg) {
  if (pCfg != NULL) {
S
Shengliang Guan 已提交
94 95 96 97
    int32_t size = taosArrayGetSize(pCfg->array);
    for (int32_t i = 0; i < size; ++i) {
      SConfigItem *pItem = taosArrayGet(pCfg->array, i);
      cfgFreeItem(pItem);
wafwerar's avatar
wafwerar 已提交
98
      taosMemoryFreeClear(pItem->name);
S
Shengliang Guan 已提交
99
    }
S
Shengliang Guan 已提交
100
    taosArrayDestroy(pCfg->array);
wafwerar's avatar
wafwerar 已提交
101
    taosMemoryFree(pCfg);
S
Shengliang Guan 已提交
102 103 104
  }
}

S
Shengliang Guan 已提交
105
int32_t cfgGetSize(SConfig *pCfg) { return taosArrayGetSize(pCfg->array); }
S
Shengliang Guan 已提交
106

S
Shengliang Guan 已提交
107
static int32_t cfgCheckAndSetTimezone(SConfigItem *pItem, const char *timezone) {
S
tfs cfg  
Shengliang Guan 已提交
108
  cfgFreeItem(pItem);
S
Shengliang Guan 已提交
109 110 111 112
  pItem->str = strdup(timezone);
  if (pItem->str == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return -1;
S
config  
Shengliang Guan 已提交
113
  }
S
Shengliang Guan 已提交
114 115 116 117 118

  return 0;
}

static int32_t cfgCheckAndSetCharset(SConfigItem *pItem, const char *charset) {
S
tfs cfg  
Shengliang Guan 已提交
119
  cfgFreeItem(pItem);
S
Shengliang Guan 已提交
120 121 122 123
  pItem->str = strdup(charset);
  if (pItem->str == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return -1;
S
config  
Shengliang Guan 已提交
124
  }
S
config  
Shengliang Guan 已提交
125

S
config  
Shengliang Guan 已提交
126 127 128
  return 0;
}

S
Shengliang Guan 已提交
129
static int32_t cfgCheckAndSetLocale(SConfigItem *pItem, const char *locale) {
S
tfs cfg  
Shengliang Guan 已提交
130
  cfgFreeItem(pItem);
S
Shengliang Guan 已提交
131 132 133
  pItem->str = strdup(locale);
  if (pItem->str == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
S
config  
Shengliang Guan 已提交
134 135
    return -1;
  }
S
config  
Shengliang Guan 已提交
136

S
config  
Shengliang Guan 已提交
137 138 139
  return 0;
}

S
Shengliang Guan 已提交
140 141 142 143 144 145 146 147
static int32_t cfgCheckAndSetDir(SConfigItem *pItem, const char *inputDir) {
  char fullDir[PATH_MAX] = {0};
  if (taosExpandDir(inputDir, fullDir, PATH_MAX) != 0) {
    terrno = TAOS_SYSTEM_ERROR(errno);
    uError("failed to expand dir:%s since %s", inputDir, terrstr());
    return -1;
  }

wafwerar's avatar
wafwerar 已提交
148
  taosMemoryFreeClear(pItem->str);
S
Shengliang Guan 已提交
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
  pItem->str = strdup(fullDir);
  if (pItem->str == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return -1;
  }

  return 0;
}

static int32_t cfgSetBool(SConfigItem *pItem, const char *value, ECfgSrcType stype) {
  bool tmp = false;
  if (strcasecmp(value, "true") == 0) {
    tmp = true;
  }
  if (atoi(value) > 0) {
    tmp = true;
  }

  pItem->bval = tmp;
S
config  
Shengliang Guan 已提交
168 169 170 171
  pItem->stype = stype;
  return 0;
}

S
config  
Shengliang Guan 已提交
172
static int32_t cfgSetInt32(SConfigItem *pItem, const char *value, ECfgSrcType stype) {
S
config  
Shengliang Guan 已提交
173
  int32_t ival = (int32_t)atoi(value);
S
Shengliang Guan 已提交
174
  if (ival < pItem->imin || ival > pItem->imax) {
175 176
    uError("cfg:%s, type:%s src:%s value:%d out of range[%" PRId64 ", %" PRId64 "]", pItem->name,
           cfgDtypeStr(pItem->dtype), cfgStypeStr(stype), ival, pItem->imin, pItem->imax);
S
config  
Shengliang Guan 已提交
177 178 179
    terrno = TSDB_CODE_OUT_OF_RANGE;
    return -1;
  }
S
config  
Shengliang Guan 已提交
180

S
Shengliang Guan 已提交
181
  pItem->i32 = ival;
S
config  
Shengliang Guan 已提交
182 183 184 185
  pItem->stype = stype;
  return 0;
}

S
config  
Shengliang Guan 已提交
186
static int32_t cfgSetInt64(SConfigItem *pItem, const char *value, ECfgSrcType stype) {
S
config  
Shengliang Guan 已提交
187
  int64_t ival = (int64_t)atoi(value);
S
Shengliang Guan 已提交
188
  if (ival < pItem->imin || ival > pItem->imax) {
189 190
    uError("cfg:%s, type:%s src:%s value:%" PRId64 " out of range[%" PRId64 ", %" PRId64 "]", pItem->name,
           cfgDtypeStr(pItem->dtype), cfgStypeStr(stype), ival, pItem->imin, pItem->imax);
S
config  
Shengliang Guan 已提交
191 192 193
    terrno = TSDB_CODE_OUT_OF_RANGE;
    return -1;
  }
S
config  
Shengliang Guan 已提交
194

S
Shengliang Guan 已提交
195
  pItem->i64 = ival;
S
config  
Shengliang Guan 已提交
196 197 198 199
  pItem->stype = stype;
  return 0;
}

S
config  
Shengliang Guan 已提交
200
static int32_t cfgSetFloat(SConfigItem *pItem, const char *value, ECfgSrcType stype) {
S
config  
Shengliang Guan 已提交
201
  float fval = (float)atof(value);
S
Shengliang Guan 已提交
202
  if (fval < pItem->fmin || fval > pItem->fmax) {
203 204
    uError("cfg:%s, type:%s src:%s value:%f out of range[%f, %f]", pItem->name, cfgDtypeStr(pItem->dtype),
           cfgStypeStr(stype), fval, pItem->fmin, pItem->fmax);
S
config  
Shengliang Guan 已提交
205 206 207
    terrno = TSDB_CODE_OUT_OF_RANGE;
    return -1;
  }
S
config  
Shengliang Guan 已提交
208

S
Shengliang Guan 已提交
209
  pItem->fval = fval;
S
config  
Shengliang Guan 已提交
210 211 212 213
  pItem->stype = stype;
  return 0;
}

S
config  
Shengliang Guan 已提交
214
static int32_t cfgSetString(SConfigItem *pItem, const char *value, ECfgSrcType stype) {
S
config  
Shengliang Guan 已提交
215 216 217
  char *tmp = strdup(value);
  if (tmp == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
218 219
    uError("cfg:%s, type:%s src:%s value:%s failed to dup since %s", pItem->name, cfgDtypeStr(pItem->dtype),
           cfgStypeStr(stype), value, terrstr());
S
config  
Shengliang Guan 已提交
220 221
    return -1;
  }
S
config  
Shengliang Guan 已提交
222

wafwerar's avatar
wafwerar 已提交
223
  taosMemoryFree(pItem->str);
S
Shengliang Guan 已提交
224
  pItem->str = tmp;
S
config  
Shengliang Guan 已提交
225 226 227 228
  pItem->stype = stype;
  return 0;
}

S
config  
Shengliang Guan 已提交
229
static int32_t cfgSetDir(SConfigItem *pItem, const char *value, ECfgSrcType stype) {
S
Shengliang Guan 已提交
230
  if (cfgCheckAndSetDir(pItem, value) != 0) {
231 232
    uError("cfg:%s, type:%s src:%s value:%s failed to dup since %s", pItem->name, cfgDtypeStr(pItem->dtype),
           cfgStypeStr(stype), value, terrstr());
S
Shengliang Guan 已提交
233 234 235 236 237 238 239 240
    return -1;
  }

  pItem->stype = stype;
  return 0;
}

static int32_t cfgSetLocale(SConfigItem *pItem, const char *value, ECfgSrcType stype) {
S
Shengliang Guan 已提交
241
  if (cfgCheckAndSetLocale(pItem, value) != 0) {
S
Shengliang Guan 已提交
242
    terrno = TSDB_CODE_OUT_OF_MEMORY;
243 244
    uError("cfg:%s, type:%s src:%s value:%s failed to dup since %s", pItem->name, cfgDtypeStr(pItem->dtype),
           cfgStypeStr(stype), value, terrstr());
S
Shengliang Guan 已提交
245 246 247 248 249 250 251 252
    return -1;
  }

  pItem->stype = stype;
  return 0;
}

static int32_t cfgSetCharset(SConfigItem *pItem, const char *value, ECfgSrcType stype) {
S
Shengliang Guan 已提交
253
  if (cfgCheckAndSetCharset(pItem, value) != 0) {
S
Shengliang Guan 已提交
254
    terrno = TSDB_CODE_OUT_OF_MEMORY;
255 256
    uError("cfg:%s, type:%s src:%s value:%s failed to dup since %s", pItem->name, cfgDtypeStr(pItem->dtype),
           cfgStypeStr(stype), value, terrstr());
S
Shengliang Guan 已提交
257 258 259 260 261 262 263 264
    return -1;
  }

  pItem->stype = stype;
  return 0;
}

static int32_t cfgSetTimezone(SConfigItem *pItem, const char *value, ECfgSrcType stype) {
S
Shengliang Guan 已提交
265
  if (cfgCheckAndSetTimezone(pItem, value) != 0) {
S
config  
Shengliang Guan 已提交
266
    terrno = TSDB_CODE_OUT_OF_MEMORY;
267 268
    uError("cfg:%s, type:%s src:%s value:%s failed to dup since %s", pItem->name, cfgDtypeStr(pItem->dtype),
           cfgStypeStr(stype), value, terrstr());
S
config  
Shengliang Guan 已提交
269 270
    return -1;
  }
S
config  
Shengliang Guan 已提交
271

S
config  
Shengliang Guan 已提交
272 273 274 275
  pItem->stype = stype;
  return 0;
}

S
tfs cfg  
Shengliang Guan 已提交
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
static int32_t cfgSetTfsItem(SConfig *pCfg, const char *name, const char *value, const char *level, const char *primary,
                             ECfgSrcType stype) {
  SConfigItem *pItem = cfgGetItem(pCfg, name);
  if (pItem == NULL) return -1;

  if (pItem->array == NULL) {
    pItem->array = taosArrayInit(16, sizeof(SDiskCfg));
    if (pItem->array == NULL) {
      terrno = TSDB_CODE_OUT_OF_MEMORY;
      return -1;
    }
  }

  SDiskCfg cfg = {0};
  tstrncpy(cfg.dir, value, sizeof(cfg.dir));
  cfg.level = atoi(level);
  cfg.primary = atoi(primary);
  void *ret = taosArrayPush(pItem->array, &cfg);
  if (ret == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return -1;
  }

  pItem->stype = stype;
  return 0;
}

S
Shengliang Guan 已提交
303 304
int32_t cfgSetItem(SConfig *pCfg, const char *name, const char *value, ECfgSrcType stype) {
  SConfigItem *pItem = cfgGetItem(pCfg, name);
S
config  
Shengliang Guan 已提交
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
  if (pItem == NULL) {
    return -1;
  }

  switch (pItem->dtype) {
    case CFG_DTYPE_BOOL:
      return cfgSetBool(pItem, value, stype);
    case CFG_DTYPE_INT32:
      return cfgSetInt32(pItem, value, stype);
    case CFG_DTYPE_INT64:
      return cfgSetInt64(pItem, value, stype);
    case CFG_DTYPE_FLOAT:
      return cfgSetFloat(pItem, value, stype);
    case CFG_DTYPE_STRING:
      return cfgSetString(pItem, value, stype);
    case CFG_DTYPE_DIR:
S
config  
Shengliang Guan 已提交
321
      return cfgSetDir(pItem, value, stype);
S
Shengliang Guan 已提交
322 323 324 325 326 327
    case CFG_DTYPE_TIMEZONE:
      return cfgSetTimezone(pItem, value, stype);
    case CFG_DTYPE_CHARSET:
      return cfgSetCharset(pItem, value, stype);
    case CFG_DTYPE_LOCALE:
      return cfgSetLocale(pItem, value, stype);
S
config  
Shengliang Guan 已提交
328 329 330 331 332 333 334 335 336
    case CFG_DTYPE_NONE:
    default:
      break;
  }

  terrno = TSDB_CODE_INVALID_CFG;
  return -1;
}

S
Shengliang Guan 已提交
337
SConfigItem *cfgGetItem(SConfig *pCfg, const char *name) {
S
Shengliang Guan 已提交
338 339 340 341 342 343
  int32_t size = taosArrayGetSize(pCfg->array);
  for (int32_t i = 0; i < size; ++i) {
    SConfigItem *pItem = taosArrayGet(pCfg->array, i);
    if (strcasecmp(pItem->name, name) == 0) {
      return pItem;
    }
S
config  
Shengliang Guan 已提交
344 345
  }

346
  // uError("name:%s, cfg not found", name);
S
Shengliang Guan 已提交
347 348
  terrno = TSDB_CODE_CFG_NOT_FOUND;
  return NULL;
S
config  
Shengliang Guan 已提交
349
}
S
Shengliang Guan 已提交
350

S
Shengliang Guan 已提交
351
static int32_t cfgAddItem(SConfig *pCfg, SConfigItem *pItem, const char *name) {
S
config  
Shengliang Guan 已提交
352
  pItem->stype = CFG_STYPE_DEFAULT;
S
Shengliang Guan 已提交
353
  pItem->name = strdup(name);
S
Shengliang Guan 已提交
354
  if (pItem->name == NULL) {
S
Shengliang Guan 已提交
355 356 357 358
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return -1;
  }

S
Shengliang Guan 已提交
359 360 361
  int32_t len = strlen(name);
  char    lowcaseName[CFG_NAME_MAX_LEN + 1] = {0};
  strntolower(lowcaseName, name, TMIN(CFG_NAME_MAX_LEN, len));
S
config  
Shengliang Guan 已提交
362

S
Shengliang Guan 已提交
363
  if (taosArrayPush(pCfg->array, pItem) == NULL) {
S
cfgtest  
Shengliang Guan 已提交
364
    if (pItem->dtype == CFG_DTYPE_STRING) {
wafwerar's avatar
wafwerar 已提交
365
      taosMemoryFree(pItem->str);
S
cfgtest  
Shengliang Guan 已提交
366
    }
wafwerar's avatar
wafwerar 已提交
367
    taosMemoryFree(pItem->name);
S
Shengliang Guan 已提交
368 369 370 371 372 373 374
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return -1;
  }

  return 0;
}

S
Shengliang Guan 已提交
375 376
int32_t cfgAddBool(SConfig *pCfg, const char *name, bool defaultVal, bool tsc) {
  SConfigItem item = {.dtype = CFG_DTYPE_BOOL, .bval = defaultVal, .tsc = tsc};
S
Shengliang Guan 已提交
377
  return cfgAddItem(pCfg, &item, name);
S
Shengliang Guan 已提交
378 379
}

S
Shengliang Guan 已提交
380
int32_t cfgAddInt32(SConfig *pCfg, const char *name, int32_t defaultVal, int64_t minval, int64_t maxval, bool tsc) {
S
config  
Shengliang Guan 已提交
381 382 383 384
  if (defaultVal < minval || defaultVal > maxval) {
    terrno = TSDB_CODE_OUT_OF_RANGE;
    return -1;
  }
S
Shengliang Guan 已提交
385

S
Shengliang Guan 已提交
386
  SConfigItem item = {.dtype = CFG_DTYPE_INT32, .i32 = defaultVal, .imin = minval, .imax = maxval, .tsc = tsc};
S
Shengliang Guan 已提交
387
  return cfgAddItem(pCfg, &item, name);
S
Shengliang Guan 已提交
388 389
}

S
Shengliang Guan 已提交
390
int32_t cfgAddInt64(SConfig *pCfg, const char *name, int64_t defaultVal, int64_t minval, int64_t maxval, bool tsc) {
S
config  
Shengliang Guan 已提交
391 392 393 394
  if (defaultVal < minval || defaultVal > maxval) {
    terrno = TSDB_CODE_OUT_OF_RANGE;
    return -1;
  }
S
Shengliang Guan 已提交
395

S
Shengliang Guan 已提交
396
  SConfigItem item = {.dtype = CFG_DTYPE_INT64, .i64 = defaultVal, .imin = minval, .imax = maxval, .tsc = tsc};
S
Shengliang Guan 已提交
397
  return cfgAddItem(pCfg, &item, name);
S
Shengliang Guan 已提交
398 399
}

S
Shengliang Guan 已提交
400
int32_t cfgAddFloat(SConfig *pCfg, const char *name, float defaultVal, double minval, double maxval, bool tsc) {
S
config  
Shengliang Guan 已提交
401 402 403 404
  if (defaultVal < minval || defaultVal > maxval) {
    terrno = TSDB_CODE_OUT_OF_RANGE;
    return -1;
  }
S
Shengliang Guan 已提交
405

S
Shengliang Guan 已提交
406
  SConfigItem item = {.dtype = CFG_DTYPE_FLOAT, .fval = defaultVal, .fmin = minval, .fmax = maxval, .tsc = tsc};
S
Shengliang Guan 已提交
407
  return cfgAddItem(pCfg, &item, name);
S
Shengliang Guan 已提交
408 409
}

S
Shengliang Guan 已提交
410 411
int32_t cfgAddString(SConfig *pCfg, const char *name, const char *defaultVal, bool tsc) {
  SConfigItem item = {.dtype = CFG_DTYPE_STRING, .tsc = tsc};
S
Shengliang Guan 已提交
412 413
  item.str = strdup(defaultVal);
  if (item.str == NULL) {
S
Shengliang Guan 已提交
414 415 416
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    return -1;
  }
S
Shengliang Guan 已提交
417
  return cfgAddItem(pCfg, &item, name);
S
Shengliang Guan 已提交
418 419
}

S
Shengliang Guan 已提交
420 421
int32_t cfgAddDir(SConfig *pCfg, const char *name, const char *defaultVal, bool tsc) {
  SConfigItem item = {.dtype = CFG_DTYPE_DIR, .tsc = tsc};
S
config  
Shengliang Guan 已提交
422
  if (cfgCheckAndSetDir(&item, defaultVal) != 0) {
S
Shengliang Guan 已提交
423 424
    return -1;
  }
S
config  
Shengliang Guan 已提交
425

S
Shengliang Guan 已提交
426
  return cfgAddItem(pCfg, &item, name);
S
config  
Shengliang Guan 已提交
427 428
}

S
Shengliang Guan 已提交
429
int32_t cfgAddLocale(SConfig *pCfg, const char *name, const char *defaultVal) {
S
Shengliang Guan 已提交
430
  SConfigItem item = {.dtype = CFG_DTYPE_LOCALE, .tsc = 1};
S
config  
Shengliang Guan 已提交
431 432 433 434
  if (cfgCheckAndSetLocale(&item, defaultVal) != 0) {
    return -1;
  }

S
Shengliang Guan 已提交
435
  return cfgAddItem(pCfg, &item, name);
S
config  
Shengliang Guan 已提交
436 437
}

S
Shengliang Guan 已提交
438
int32_t cfgAddCharset(SConfig *pCfg, const char *name, const char *defaultVal) {
S
Shengliang Guan 已提交
439
  SConfigItem item = {.dtype = CFG_DTYPE_CHARSET, .tsc = 1};
S
config  
Shengliang Guan 已提交
440 441 442 443
  if (cfgCheckAndSetCharset(&item, defaultVal) != 0) {
    return -1;
  }

S
Shengliang Guan 已提交
444
  return cfgAddItem(pCfg, &item, name);
S
config  
Shengliang Guan 已提交
445 446
}

S
Shengliang Guan 已提交
447
int32_t cfgAddTimezone(SConfig *pCfg, const char *name, const char *defaultVal) {
S
Shengliang Guan 已提交
448
  SConfigItem item = {.dtype = CFG_DTYPE_TIMEZONE, .tsc = 1};
S
config  
Shengliang Guan 已提交
449 450 451 452
  if (cfgCheckAndSetTimezone(&item, defaultVal) != 0) {
    return -1;
  }

S
Shengliang Guan 已提交
453
  return cfgAddItem(pCfg, &item, name);
S
Shengliang Guan 已提交
454
}
S
Shengliang Guan 已提交
455 456 457

const char *cfgStypeStr(ECfgSrcType type) {
  switch (type) {
S
config  
Shengliang Guan 已提交
458
    case CFG_STYPE_DEFAULT:
S
Shengliang Guan 已提交
459
      return "default";
S
config  
Shengliang Guan 已提交
460
    case CFG_STYPE_CFG_FILE:
S
Shengliang Guan 已提交
461
      return "cfg_file";
S
config  
Shengliang Guan 已提交
462
    case CFG_STYPE_ENV_FILE:
S
Shengliang Guan 已提交
463
      return "env_file";
S
config  
Shengliang Guan 已提交
464
    case CFG_STYPE_ENV_VAR:
S
Shengliang Guan 已提交
465
      return "env_var";
S
config  
Shengliang Guan 已提交
466
    case CFG_STYPE_APOLLO_URL:
S
Shengliang Guan 已提交
467
      return "apollo_url";
S
config  
Shengliang Guan 已提交
468 469
    case CFG_STYPE_ARG_LIST:
      return "arg_list";
S
Shengliang Guan 已提交
470 471
    case CFG_STYPE_TAOS_OPTIONS:
      return "taos_options";
wafwerar's avatar
wafwerar 已提交
472 473
    case CFG_STYPE_ENV_CMD:
      return "env_cmd";
S
Shengliang Guan 已提交
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
    default:
      return "invalid";
  }
}

const char *cfgDtypeStr(ECfgDataType type) {
  switch (type) {
    case CFG_DTYPE_NONE:
      return "none";
    case CFG_DTYPE_BOOL:
      return "bool";
    case CFG_DTYPE_INT32:
      return "int32";
    case CFG_DTYPE_INT64:
      return "int64";
    case CFG_DTYPE_FLOAT:
      return "float";
    case CFG_DTYPE_STRING:
      return "string";
    case CFG_DTYPE_DIR:
      return "dir";
S
config  
Shengliang Guan 已提交
495 496 497 498 499 500
    case CFG_DTYPE_LOCALE:
      return "locale";
    case CFG_DTYPE_CHARSET:
      return "charset";
    case CFG_DTYPE_TIMEZONE:
      return "timezone";
S
Shengliang Guan 已提交
501 502 503 504 505
    default:
      return "invalid";
  }
}

S
Shengliang Guan 已提交
506 507
void cfgDumpCfg(SConfig *pCfg, bool tsc, bool dump) {
  if (dump) {
S
Shengliang Guan 已提交
508
    printf("                     global config");
S
Shengliang Guan 已提交
509 510 511 512
    printf("\n");
    printf("=================================================================");
    printf("\n");
  } else {
S
Shengliang Guan 已提交
513
    uInfo("                     global config");
S
Shengliang Guan 已提交
514 515
    uInfo("=================================================================");
  }
S
Shengliang Guan 已提交
516 517 518

  char src[CFG_SRC_PRINT_LEN + 1] = {0};
  char name[CFG_NAME_PRINT_LEN + 1] = {0};
S
Shengliang Guan 已提交
519

S
Shengliang Guan 已提交
520 521 522
  int32_t size = taosArrayGetSize(pCfg->array);
  for (int32_t i = 0; i < size; ++i) {
    SConfigItem *pItem = taosArrayGet(pCfg->array, i);
S
Shengliang Guan 已提交
523
    if (tsc && !pItem->tsc) continue;
524 525
    if (dump && strcmp(pItem->name, "scriptDir") == 0) continue;
    if (dump && strcmp(pItem->name, "simDebugFlag") == 0) continue;
S
Shengliang Guan 已提交
526 527 528
    tstrncpy(src, cfgStypeStr(pItem->stype), CFG_SRC_PRINT_LEN);
    for (int32_t i = 0; i < CFG_SRC_PRINT_LEN; ++i) {
      if (src[i] == 0) src[i] = ' ';
S
Shengliang Guan 已提交
529 530
    }

S
Shengliang Guan 已提交
531 532 533 534
    tstrncpy(name, pItem->name, CFG_NAME_PRINT_LEN);
    for (int32_t i = 0; i < CFG_NAME_PRINT_LEN; ++i) {
      if (name[i] == 0) name[i] = ' ';
    }
S
Shengliang Guan 已提交
535 536 537

    switch (pItem->dtype) {
      case CFG_DTYPE_BOOL:
S
Shengliang Guan 已提交
538 539 540 541 542 543 544
        if (dump) {
          printf("%s %s %u", src, name, pItem->bval);
          printf("\n");
        } else {
          uInfo("%s %s %u", src, name, pItem->bval);
        }

S
Shengliang Guan 已提交
545 546
        break;
      case CFG_DTYPE_INT32:
S
Shengliang Guan 已提交
547 548 549 550 551 552
        if (dump) {
          printf("%s %s %d", src, name, pItem->i32);
          printf("\n");
        } else {
          uInfo("%s %s %d", src, name, pItem->i32);
        }
S
Shengliang Guan 已提交
553 554
        break;
      case CFG_DTYPE_INT64:
S
Shengliang Guan 已提交
555 556 557 558 559 560
        if (dump) {
          printf("%s %s %" PRId64, src, name, pItem->i64);
          printf("\n");
        } else {
          uInfo("%s %s %" PRId64, src, name, pItem->i64);
        }
S
Shengliang Guan 已提交
561 562
        break;
      case CFG_DTYPE_FLOAT:
S
Shengliang Guan 已提交
563
        if (dump) {
564
          printf("%s %s %.2f", src, name, pItem->fval);
S
Shengliang Guan 已提交
565 566
          printf("\n");
        } else {
567
          uInfo("%s %s %.2f", src, name, pItem->fval);
S
Shengliang Guan 已提交
568
        }
S
Shengliang Guan 已提交
569 570 571 572 573 574
        break;
      case CFG_DTYPE_STRING:
      case CFG_DTYPE_DIR:
      case CFG_DTYPE_LOCALE:
      case CFG_DTYPE_CHARSET:
      case CFG_DTYPE_TIMEZONE:
575
      case CFG_DTYPE_NONE:
S
Shengliang Guan 已提交
576 577 578 579 580 581
        if (dump) {
          printf("%s %s %s", src, name, pItem->str);
          printf("\n");
        } else {
          uInfo("%s %s %s", src, name, pItem->str);
        }
S
Shengliang Guan 已提交
582 583 584 585
        break;
    }
  }

S
Shengliang Guan 已提交
586 587 588 589 590 591
  if (dump) {
    printf("=================================================================");
    printf("\n");
  } else {
    uInfo("=================================================================");
  }
S
Shengliang Guan 已提交
592
}
S
Shengliang Guan 已提交
593 594

int32_t cfgLoadFromEnvVar(SConfig *pConfig) {
wafwerar's avatar
wafwerar 已提交
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 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
  char   *line = NULL, *name, *value, *value2, *value3;
  int32_t olen, vlen, vlen2, vlen3;
  ssize_t _bytes = 0;
  TdCmdPtr pCmd = taosOpenCmd("set");
  if (pCmd == NULL) {
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }
  while (!taosEOFCmd(pCmd)) {
    name = value = value2 = value3 = NULL;
    olen = vlen = vlen2 = vlen3 = 0;

    _bytes = taosGetLineCmd(pCmd, &line);
    if (_bytes < 0) {
      break;
    }
    if(line[_bytes - 1] == '\n') line[_bytes - 1] = 0;
    taosEnvToCfg(line, line);

    paGetToken(line, &name, &olen);
    if (olen == 0) continue;
    name[olen] = 0;

    paGetToken(name + olen + 1, &value, &vlen);
    if (vlen == 0) continue;
    value[vlen] = 0;

    paGetToken(value + vlen + 1, &value2, &vlen2);
    if (vlen2 != 0) {
      value2[vlen2] = 0;
      paGetToken(value2 + vlen2 + 1, &value3, &vlen3);
      if (vlen3 != 0) value3[vlen3] = 0;
    }

    cfgSetItem(pConfig, name, value, CFG_STYPE_ENV_VAR);
    if (value2 != NULL && value3 != NULL && value2[0] != 0 && value3[0] != 0 && strcasecmp(name, "dataDir") == 0) {
      cfgSetTfsItem(pConfig, name, value, value2, value3, CFG_STYPE_ENV_VAR);
    }
  }

  taosCloseCmd(&pCmd);
  if (line != NULL) taosMemoryFreeClear(line);

  uInfo("load from env variables cfg success");
S
Shengliang Guan 已提交
639 640 641
  return 0;
}

wafwerar's avatar
wafwerar 已提交
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 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 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742
int32_t cfgLoadFromEnvCmd(SConfig *pConfig, const char **envCmd) {
  char   *buf, *name, *value, *value2, *value3;
  int32_t olen, vlen, vlen2, vlen3;
  int32_t index = 0;
  if (envCmd == NULL) return 0;
  while (envCmd[index]!=NULL) {
    buf = taosMemoryMalloc(strlen(envCmd[index]));
    taosEnvToCfg(envCmd[index], buf);
    index++;
    
    name = value = value2 = value3 = NULL;
    olen = vlen = vlen2 = vlen3 = 0;

    paGetToken(buf, &name, &olen);
    if (olen == 0) continue;
    name[olen] = 0;

    paGetToken(name + olen + 1, &value, &vlen);
    if (vlen == 0) continue;
    value[vlen] = 0;

    paGetToken(value + vlen + 1, &value2, &vlen2);
    if (vlen2 != 0) {
      value2[vlen2] = 0;
      paGetToken(value2 + vlen2 + 1, &value3, &vlen3);
      if (vlen3 != 0) value3[vlen3] = 0;
    }

    cfgSetItem(pConfig, name, value, CFG_STYPE_ENV_CMD);
    if (value2 != NULL && value3 != NULL && value2[0] != 0 && value3[0] != 0 && strcasecmp(name, "dataDir") == 0) {
      cfgSetTfsItem(pConfig, name, value, value2, value3, CFG_STYPE_ENV_CMD);
    }

    taosMemoryFree(buf);
  }

  uInfo("load from env cmd cfg success");
  return 0;
}

int32_t cfgLoadFromEnvFile(SConfig *pConfig, const char *envFile) {
  char   *line = NULL, *name, *value, *value2, *value3;
  int32_t olen, vlen, vlen2, vlen3;
  ssize_t _bytes = 0;

  const char *filepath = ".env";
  if (envFile != NULL && strlen(envFile)>0) {
    if (!taosCheckExistFile(envFile)) {
      uError("fial to load env file: %s", envFile);
      return -1;
    }
    filepath = envFile;
  }else {
    if (!taosCheckExistFile(filepath)) {
      uInfo("fial to load env file: %s", filepath);
      return 0;
    }
  }

  TdFilePtr pFile = taosOpenFile(filepath, TD_FILE_READ | TD_FILE_STREAM);
  if (pFile == NULL) {
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }

  while (!taosEOFFile(pFile)) {
    name = value = value2 = value3 = NULL;
    olen = vlen = vlen2 = vlen3 = 0;

    _bytes = taosGetLineFile(pFile, &line);
    if (_bytes <= 0) {
      break;
    }
    if(line[_bytes - 1] == '\n') line[_bytes - 1] = 0;
    taosEnvToCfg(line, line);

    paGetToken(line, &name, &olen);
    if (olen == 0) continue;
    name[olen] = 0;

    paGetToken(name + olen + 1, &value, &vlen);
    if (vlen == 0) continue;
    value[vlen] = 0;

    paGetToken(value + vlen + 1, &value2, &vlen2);
    if (vlen2 != 0) {
      value2[vlen2] = 0;
      paGetToken(value2 + vlen2 + 1, &value3, &vlen3);
      if (vlen3 != 0) value3[vlen3] = 0;
    }

    cfgSetItem(pConfig, name, value, CFG_STYPE_ENV_FILE);
    if (value2 != NULL && value3 != NULL && value2[0] != 0 && value3[0] != 0 && strcasecmp(name, "dataDir") == 0) {
      cfgSetTfsItem(pConfig, name, value, value2, value3, CFG_STYPE_ENV_FILE);
    }
  }

  taosCloseFile(&pFile);
  if (line != NULL) taosMemoryFreeClear(line);

  uInfo("load from env cfg file %s success", filepath);
S
Shengliang Guan 已提交
743 744 745 746
  return 0;
}

int32_t cfgLoadFromCfgFile(SConfig *pConfig, const char *filepath) {
747
  char   *line = NULL, *name, *value, *value2, *value3;
S
Shengliang Guan 已提交
748
  int32_t olen, vlen, vlen2, vlen3;
S
Shengliang Guan 已提交
749
  ssize_t _bytes = 0;
750
  int32_t code = 0;
751

752
  TdFilePtr pFile = taosOpenFile(filepath, TD_FILE_READ | TD_FILE_STREAM);
753
  if (pFile == NULL) {
754 755 756 757 758 759 760 761 762
    // success when the file does not exist
    if (errno == ENOENT) {
      terrno = TAOS_SYSTEM_ERROR(errno);
      uInfo("failed to load from cfg file %s since %s, use default parameters", filepath, terrstr());
      return 0;
    } else {
      uError("failed to load from cfg file %s since %s", filepath, terrstr());
      return -1;
    }
S
Shengliang Guan 已提交
763 764
  }

765
  while (!taosEOFFile(pFile)) {
S
Shengliang Guan 已提交
766 767 768
    name = value = value2 = value3 = NULL;
    olen = vlen = vlen2 = vlen3 = 0;

769
    _bytes = taosGetLineFile(pFile, &line);
wafwerar's avatar
wafwerar 已提交
770
    if (_bytes <= 0) {
S
Shengliang Guan 已提交
771 772 773
      break;
    }

wafwerar's avatar
wafwerar 已提交
774
    if(line[_bytes - 1] == '\n') line[_bytes - 1] = 0;
S
Shengliang Guan 已提交
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790

    paGetToken(line, &name, &olen);
    if (olen == 0) continue;
    name[olen] = 0;

    paGetToken(name + olen + 1, &value, &vlen);
    if (vlen == 0) continue;
    value[vlen] = 0;

    paGetToken(value + vlen + 1, &value2, &vlen2);
    if (vlen2 != 0) {
      value2[vlen2] = 0;
      paGetToken(value2 + vlen2 + 1, &value3, &vlen3);
      if (vlen3 != 0) value3[vlen3] = 0;
    }

791 792
    code = cfgSetItem(pConfig, name, value, CFG_STYPE_CFG_FILE);
    if (code != 0 && terrno != TSDB_CODE_CFG_NOT_FOUND) break;
S
Shengliang Guan 已提交
793
    if (value2 != NULL && value3 != NULL && value2[0] != 0 && value3[0] != 0 && strcasecmp(name, "dataDir") == 0) {
794 795
      code = cfgSetTfsItem(pConfig, name, value, value2, value3, CFG_STYPE_CFG_FILE);
      if (code != 0 && terrno != TSDB_CODE_CFG_NOT_FOUND) break;
S
Shengliang Guan 已提交
796
    }
S
Shengliang Guan 已提交
797 798
  }

799
  taosCloseFile(&pFile);
wafwerar's avatar
wafwerar 已提交
800
  if (line != NULL) taosMemoryFreeClear(line);
S
Shengliang Guan 已提交
801

802
  if (code == 0 || (code != 0 && terrno == TSDB_CODE_CFG_NOT_FOUND)) {
803
    uInfo("load from cfg file %s success", filepath);
804
    return 0;
805 806
  } else {
    uError("failed to load from cfg file %s since %s", filepath, terrstr());
807
    return -1;
808
  }
S
Shengliang Guan 已提交
809 810 811
}

int32_t cfgLoadFromApollUrl(SConfig *pConfig, const char *url) {
wafwerar's avatar
wafwerar 已提交
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 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
  char   *cfgLineBuf = NULL, *name, *value, *value2, *value3;
  int32_t olen, vlen, vlen2, vlen3;
  if (url == NULL || strlen(url) == 0) {
    uInfo("fail to load apoll url");
    return 0;
  }
  
  char *p = strchr(url, ':');
  if (p == NULL) {
    uError("fail to load apoll url: %s, unknown format", url);
    return -1;
  }
  p++;

  if (bcmp(url, "jsonFile", 8) == 0) {
    char *filepath = p;
    if (!taosCheckExistFile(filepath)) {
      uError("fial to load json file: %s", filepath);
      return -1;
    }

    TdFilePtr pFile = taosOpenFile(filepath, TD_FILE_READ);
    if (pFile == NULL) {
      terrno = TAOS_SYSTEM_ERROR(errno);
      return -1;
    }
    size_t fileSize = taosLSeekFile(pFile, 0, SEEK_END);
    char *buf = taosMemoryMalloc(fileSize);
    taosLSeekFile(pFile, 0, SEEK_SET);
    if(taosReadFile(pFile, buf, fileSize) <= 0) {
      taosCloseFile(&pFile);
      uError("load json file error: %s", filepath);
      return -1;
    }
    taosCloseFile(&pFile);
    SJson* pJson = tjsonParse(buf);
    if (NULL == pJson) {
      const char *jsonParseError = tjsonGetError();
      if (jsonParseError != NULL) {
        uError("load json file parse error: %s", jsonParseError);
      }
      return -1;
    }
    taosMemoryFreeClear(buf);

    int32_t jsonArraySize = tjsonGetArraySize(pJson);
    for(int32_t i = 0; i < jsonArraySize; i++) {
      cJSON* item = tjsonGetArrayItem(pJson, i);
      if (item == NULL) break;
      char *itemName = NULL, *itemValueString = NULL;
      tjsonGetObjectName(item, &itemName);
      tjsonGetObjectName(item, &itemName);
      tjsonGetObjectValueString(item, &itemValueString);
      if (itemValueString != NULL && itemName != NULL) {
        size_t itemNameLen = strlen(itemName);
        size_t itemValueStringLen = strlen(itemValueString);
        cfgLineBuf = taosMemoryMalloc(itemNameLen + itemValueStringLen + 2);
        memcpy(cfgLineBuf, itemName, itemNameLen);
        cfgLineBuf[itemNameLen] = ' ';
        memcpy(&cfgLineBuf[itemNameLen+1], itemValueString, itemValueStringLen);
        cfgLineBuf[itemNameLen + itemValueStringLen + 1] = '\0';

        paGetToken(cfgLineBuf, &name, &olen);
        if (olen == 0) continue;
        name[olen] = 0;

        paGetToken(name + olen + 1, &value, &vlen);
        if (vlen == 0) continue;
        value[vlen] = 0;

        paGetToken(value + vlen + 1, &value2, &vlen2);
        if (vlen2 != 0) {
          value2[vlen2] = 0;
          paGetToken(value2 + vlen2 + 1, &value3, &vlen3);
          if (vlen3 != 0) value3[vlen3] = 0;
        }
        printf("%s(%d) %s name=%s, value=%s\n", __FILE__, __LINE__,__func__,name, value);
        cfgSetItem(pConfig, name, value, CFG_STYPE_APOLLO_URL);
        if (value2 != NULL && value3 != NULL && value2[0] != 0 && value3[0] != 0 && strcasecmp(name, "dataDir") == 0) {
          cfgSetTfsItem(pConfig, name, value, value2, value3, CFG_STYPE_APOLLO_URL);
        }
      }
    }
    tjsonDelete(pJson);

  // } else if (bcmp(url, "jsonUrl", 7) == 0) {
  // } else if (bcmp(url, "etcdUrl", 7) == 0) {
  } else {
    uError("Unsupported url: %s", url);
    return -1;
  }

  uInfo("load from apoll url not implemented yet");
S
Shengliang Guan 已提交
905
  return 0;
906
}
wafwerar's avatar
wafwerar 已提交
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001

int32_t cfgGetApollUrl(const char **envCmd, const char *envFile, char* apolloUrl) {
  int32_t index = 0;
  if (envCmd == NULL) return 0;
  while (envCmd[index]!=NULL) {
    if (bcmp(envCmd[index], "TAOS_APOLL_URL", 14) == 0) {
      char *p = strchr(envCmd[index], '=');
      if (p != NULL) {
        p++;
        if (*p == '\'') {
          p++;
          p[strlen(p)-1] = '\0';
        }
        memcpy(apolloUrl, p, TMIN(strlen(p)+1,PATH_MAX));
        uInfo("get apollo url from env cmd success");
        return 0;
      }
    }
    index++;
  }

  char   *line = NULL;
  ssize_t _bytes = 0;
  TdCmdPtr pCmd = taosOpenCmd("set");
  if (pCmd != NULL) {
    while (!taosEOFCmd(pCmd)) {
      _bytes = taosGetLineCmd(pCmd, &line);
      if (_bytes < 0) {
        break;
      }
      if(line[_bytes - 1] == '\n') line[_bytes - 1] = 0;
      if (bcmp(line, "TAOS_APOLL_URL", 14) == 0) {
        char *p = strchr(line, '=');
        if (p != NULL) {
          p++;
          if (*p == '\'') {
            p++;
            p[strlen(p)-1] = '\0';
          }
          memcpy(apolloUrl, p, TMIN(strlen(p)+1,PATH_MAX));
          uInfo("get apollo url from env variables success, apolloUrl=%s",apolloUrl);
          taosCloseCmd(&pCmd);
          if (line != NULL) taosMemoryFreeClear(line);
          return 0;
        }
      }
    }
    taosCloseCmd(&pCmd);
    if (line != NULL) taosMemoryFreeClear(line);
  }

  const char *filepath = ".env";
  if (envFile != NULL && strlen(envFile)>0) {
    if (!taosCheckExistFile(envFile)) {
      uError("fial to load env file: %s", envFile);
      return -1;
    }
    filepath = envFile;
  }else {
    if (!taosCheckExistFile(filepath)) {
      uInfo("fial to load env file: %s", filepath);
      return 0;
    }
  }
  TdFilePtr pFile = taosOpenFile(filepath, TD_FILE_READ | TD_FILE_STREAM);
  if (pFile != NULL) {
    while (!taosEOFFile(pFile)) {
      _bytes = taosGetLineFile(pFile, &line);
      if (_bytes <= 0) {
        break;
      }
      if(line[_bytes - 1] == '\n') line[_bytes - 1] = 0;
      if (bcmp(line, "TAOS_APOLL_URL", 14) == 0) {
        char *p = strchr(line, '=');
        if (p != NULL) {
          p++;
          if (*p == '\'') {
            p++;
            p[strlen(p)-1] = '\0';
          }
          memcpy(apolloUrl, p, TMIN(strlen(p)+1,PATH_MAX));
          taosCloseFile(&pFile);
          if (line != NULL) taosMemoryFreeClear(line);
          uInfo("get apollo url from env file success");
          return 0;
        }
      }
    }
    taosCloseFile(&pFile);
    if (line != NULL) taosMemoryFreeClear(line);
  }

  uInfo("fail get apollo url from cmd env file");
  return -1;
}