dmEnv.c 11.5 KB
Newer Older
S
shm  
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
17
#include "dmMgmt.h"
S
shm  
Shengliang Guan 已提交
18

K
kailixu 已提交
19 20 21 22
#define STR_CASE_CMP(s, d)   (0 == strcasecmp((s), (d)))
#define STR_STR_CMP(s, d)    (strstr((s), (d)))
#define STR_INT_CMP(s, d, c) (taosStr2Int32(s, 0, 10) c(d))
#define STR_STR_SIGN         ("ia")
K
kailixu 已提交
23 24 25 26 27 28 29 30 31 32 33 34
#define DM_INIT_MON()                   \
  do {                                  \
    code = (int32_t)(2147483648 | 298); \
    strncpy(stName, tsVersionName, 64); \
    monCfg.maxLogs = tsMonitorMaxLogs;  \
    monCfg.port = tsMonitorPort;        \
    monCfg.server = tsMonitorFqdn;      \
    monCfg.comp = tsMonitorComp;        \
    if (monInit(&monCfg) != 0) {        \
      if (terrno != 0) code = terrno;   \
      goto _exit;                       \
    }                                   \
K
kailixu 已提交
35 36 37 38 39 40 41 42 43 44
  } while (0)

#define DM_ERR_RTN(c) \
  do {                \
    code = (c);       \
    goto _exit;       \
  } while (0)

static SDnode      globalDnode = {0};
static const char *dmOS[10] = {"Ubuntu",  "CentOS Linux", "Red Hat", "Debian GNU", "CoreOS",
K
kailixu 已提交
45
                               "FreeBSD", "openSUSE",     "SLES",    "Fedora",     "macOS"};
46

S
Shengliang Guan 已提交
47
SDnode *dmInstance() { return &globalDnode; }
48 49 50

static int32_t dmCheckRepeatInit(SDnode *pDnode) {
  if (atomic_val_compare_exchange_8(&pDnode->once, DND_ENV_INIT, DND_ENV_READY) != DND_ENV_INIT) {
S
Shengliang Guan 已提交
51
    dError("env is already initialized");
S
shm  
Shengliang Guan 已提交
52 53 54
    terrno = TSDB_CODE_REPEAT_INIT;
    return -1;
  }
55 56
  return 0;
}
S
shm  
Shengliang Guan 已提交
57

58
static int32_t dmInitSystem() {
S
shm  
Shengliang Guan 已提交
59 60 61
  taosIgnSIGPIPE();
  taosBlockSIGPIPE();
  taosResolveCRC();
62 63
  return 0;
}
S
shm  
Shengliang Guan 已提交
64

65
static int32_t dmInitMonitor() {
K
kailixu 已提交
66
  int32_t code = 0;
S
Shengliang 已提交
67
  SMonCfg monCfg = {0};
K
kailixu 已提交
68 69 70 71
  char    reName[64] = {0};
  char    stName[64] = {0};
  char    ver[64] = {0};

K
kailixu 已提交
72 73 74
  DM_INIT_MON();

  if (STR_STR_CMP(stName, STR_STR_SIGN)) {
K
kailixu 已提交
75 76 77
    DM_ERR_RTN(0);
  }
  if (taosGetOsReleaseName(reName, stName, ver, 64) != 0) {
K
kailixu 已提交
78
    DM_ERR_RTN(code);
K
kailixu 已提交
79
  }
K
kailixu 已提交
80
  if (STR_CASE_CMP(stName, dmOS[0])) {
K
kailixu 已提交
81 82 83
    if (STR_INT_CMP(ver, 17, >)) {
      DM_ERR_RTN(0);
    }
K
kailixu 已提交
84
  } else if (STR_CASE_CMP(stName, dmOS[1])) {
K
kailixu 已提交
85 86 87
    if (STR_INT_CMP(ver, 6, >)) {
      DM_ERR_RTN(0);
    }
K
kailixu 已提交
88 89 90
  } else if (STR_STR_CMP(stName, dmOS[2]) || STR_STR_CMP(stName, dmOS[3]) || STR_STR_CMP(stName, dmOS[4]) ||
             STR_STR_CMP(stName, dmOS[5]) || STR_STR_CMP(stName, dmOS[6]) || STR_STR_CMP(stName, dmOS[7]) ||
             STR_STR_CMP(stName, dmOS[8]) || STR_STR_CMP(stName, dmOS[9])) {
K
kailixu 已提交
91 92 93 94
    DM_ERR_RTN(0);
  }

_exit:
K
kailixu 已提交
95
  if (code) terrno = code;
K
kailixu 已提交
96
  return code;
97 98
}

wafwerar's avatar
wafwerar 已提交
99 100
static bool dmCheckDiskSpace() {
  osUpdate();
101
  // sufficiency
102
  if (!osDataSpaceSufficient()) {
103 104 105
    dWarn("free data disk size: %f GB, not sufficient, expected %f GB at least",
          (double)tsDataSpace.size.avail / 1024.0 / 1024.0 / 1024.0,
          (double)tsDataSpace.reserved / 1024.0 / 1024.0 / 1024.0);
wafwerar's avatar
wafwerar 已提交
106
  }
107
  if (!osLogSpaceSufficient()) {
108 109 110
    dWarn("free log disk size: %f GB, not sufficient, expected %f GB at least",
          (double)tsLogSpace.size.avail / 1024.0 / 1024.0 / 1024.0,
          (double)tsLogSpace.reserved / 1024.0 / 1024.0 / 1024.0);
wafwerar's avatar
wafwerar 已提交
111
  }
112
  if (!osTempSpaceSufficient()) {
113 114 115
    dWarn("free temp disk size: %f GB, not sufficient, expected %f GB at least",
          (double)tsTempSpace.size.avail / 1024.0 / 1024.0 / 1024.0,
          (double)tsTempSpace.reserved / 1024.0 / 1024.0 / 1024.0);
wafwerar's avatar
wafwerar 已提交
116
  }
117 118 119 120
  // availability
  bool ret = true;
  if (!osDataSpaceAvailable()) {
    dError("data disk space unavailable, i.e. %s", tsDataDir);
121
    terrno = TSDB_CODE_NO_DISKSPACE;
122 123 124 125
    ret = false;
  }
  if (!osLogSpaceAvailable()) {
    dError("log disk space unavailable, i.e. %s", tsLogDir);
126
    terrno = TSDB_CODE_NO_DISKSPACE;
127 128 129 130
    ret = false;
  }
  if (!osTempSpaceAvailable()) {
    dError("temp disk space unavailable, i.e. %s", tsTempDir);
131
    terrno = TSDB_CODE_NO_DISKSPACE;
132 133 134
    ret = false;
  }
  return ret;
wafwerar's avatar
wafwerar 已提交
135 136 137
}

static bool dmCheckDataDirVersion() {
138
  char checkDataDirJsonFileName[PATH_MAX] = {0};
wafwerar's avatar
wafwerar 已提交
139 140
  snprintf(checkDataDirJsonFileName, PATH_MAX, "%s/dnode/dnodeCfg.json", tsDataDir);
  if (taosCheckExistFile(checkDataDirJsonFileName)) {
H
Hongze Cheng 已提交
141 142
    dError("The default data directory %s contains old data of tdengine 2.x, please clear it before running!",
           tsDataDir);
wafwerar's avatar
wafwerar 已提交
143 144 145 146 147
    return false;
  }
  return true;
}

148
int32_t dmInit() {
S
Shengliang Guan 已提交
149
  dInfo("start to init dnode env");
wafwerar's avatar
wafwerar 已提交
150
  if (!dmCheckDataDirVersion()) return -1;
wafwerar's avatar
wafwerar 已提交
151
  if (!dmCheckDiskSpace()) return -1;
152
  if (dmCheckRepeatInit(dmInstance()) != 0) return -1;
153 154
  if (dmInitSystem() != 0) return -1;
  if (dmInitMonitor() != 0) return -1;
155
  if (dmInitDnode(dmInstance()) != 0) return -1;
S
Shengliang 已提交
156

S
Shengliang Guan 已提交
157
  dInfo("dnode env is initialized");
S
shm  
Shengliang Guan 已提交
158 159 160
  return 0;
}

161 162
static int32_t dmCheckRepeatCleanup(SDnode *pDnode) {
  if (atomic_val_compare_exchange_8(&pDnode->once, DND_ENV_READY, DND_ENV_CLEANUP) != DND_ENV_READY) {
S
Shengliang Guan 已提交
163
    dError("dnode env is already cleaned up");
164
    return -1;
S
shm  
Shengliang Guan 已提交
165
  }
166 167 168 169
  return 0;
}

void dmCleanup() {
S
Shengliang Guan 已提交
170
  dDebug("start to cleanup dnode env");
171 172 173
  SDnode *pDnode = dmInstance();
  if (dmCheckRepeatCleanup(pDnode) != 0) return;
  dmCleanupDnode(pDnode);
S
shm  
Shengliang Guan 已提交
174
  monCleanup();
S
Shengliang Guan 已提交
175
  syncCleanUp();
S
shm  
Shengliang Guan 已提交
176
  walCleanUp();
S
Shengliang Guan 已提交
177
  udfcClose();
S
Shengliang 已提交
178
  udfStopUdfd();
S
shm  
Shengliang Guan 已提交
179
  taosStopCacheRefreshWorker();
S
Shengliang Guan 已提交
180
  dInfo("dnode env is cleaned up");
181 182

  taosCleanupCfg();
183
  taosCloseLog();
184 185 186
}

void dmStop() {
187
  SDnode *pDnode = dmInstance();
188 189 190 191
  pDnode->stop = true;
}

int32_t dmRun() {
192
  SDnode *pDnode = dmInstance();
193 194 195 196
  return dmRunDnode(pDnode);
}

static int32_t dmProcessCreateNodeReq(EDndNodeType ntype, SRpcMsg *pMsg) {
197
  SDnode *pDnode = dmInstance();
198 199 200 201

  SMgmtWrapper *pWrapper = dmAcquireWrapper(pDnode, ntype);
  if (pWrapper != NULL) {
    dmReleaseWrapper(pWrapper);
202 203 204 205 206 207 208 209 210 211 212 213 214
    switch (ntype) {
      case MNODE:
        terrno = TSDB_CODE_MNODE_ALREADY_DEPLOYED;
        break;
      case QNODE:
        terrno = TSDB_CODE_QNODE_ALREADY_DEPLOYED;
        break;
      case SNODE:
        terrno = TSDB_CODE_SNODE_ALREADY_DEPLOYED;
        break;
      default:
        terrno = TSDB_CODE_APP_ERROR;
    }
215 216 217 218
    dError("failed to create node since %s", terrstr());
    return -1;
  }

C
cadem 已提交
219 220
  dInfo("start to process create-node-request");

221 222
  pWrapper = &pDnode->wrappers[ntype];
  if (taosMkDir(pWrapper->path) != 0) {
223
    dmReleaseWrapper(pWrapper);
224 225 226 227 228
    terrno = TAOS_SYSTEM_ERROR(errno);
    dError("failed to create dir:%s since %s", pWrapper->path, terrstr());
    return -1;
  }

229
  taosThreadMutexLock(&pDnode->mutex);
230 231
  SMgmtInputOpt input = dmBuildMgmtInputOpt(pWrapper);

232
  dInfo("node:%s, start to create", pWrapper->name);
233 234 235 236
  int32_t code = (*pWrapper->func.createFp)(&input, pMsg);
  if (code != 0) {
    dError("node:%s, failed to create since %s", pWrapper->name, terrstr());
  } else {
237
    dInfo("node:%s, has been created", pWrapper->name);
S
Shengliang Guan 已提交
238
    code = dmOpenNode(pWrapper);
S
Shengliang Guan 已提交
239
    if (code == 0) {
S
Shengliang Guan 已提交
240 241
      code = dmStartNode(pWrapper);
    }
242
    pWrapper->deployed = true;
S
Shengliang Guan 已提交
243
    pWrapper->required = true;
244 245 246 247 248 249
  }

  taosThreadMutexUnlock(&pDnode->mutex);
  return code;
}

C
cadem 已提交
250 251 252 253 254 255 256 257 258 259 260 261 262 263
static int32_t dmProcessAlterNodeTypeReq(EDndNodeType ntype, SRpcMsg *pMsg) {
  SDnode *pDnode = dmInstance();

  SMgmtWrapper *pWrapper = dmAcquireWrapper(pDnode, ntype);
  if (pWrapper == NULL) {
    dError("fail to process alter node type since node not exist");
    return -1;
  }
  dmReleaseWrapper(pWrapper);

  dInfo("node:%s, start to process alter-node-type-request", pWrapper->name);

  pWrapper = &pDnode->wrappers[ntype];

C
cadem 已提交
264 265 266 267
  if(pWrapper->func.nodeRoleFp != NULL){
    ESyncRole role = (*pWrapper->func.nodeRoleFp)(pWrapper->pMgmt);
    dInfo("node:%s, checking node role:%d", pWrapper->name, role);
    if(role == TAOS_SYNC_ROLE_VOTER){
D
dmchen 已提交
268
      dError("node:%s, failed to alter node type since node already is role:%d", pWrapper->name, role);
C
cadem 已提交
269 270 271 272 273
      terrno = TSDB_CODE_MNODE_ALREADY_IS_VOTER;
      return -1;
    }
  }

C
cadem 已提交
274 275
  if(pWrapper->func.isCatchUpFp != NULL){
    dInfo("node:%s, checking node catch up", pWrapper->name);
C
cadem 已提交
276 277
    if((*pWrapper->func.isCatchUpFp)(pWrapper->pMgmt) != 1){
      terrno = TSDB_CODE_MNODE_NOT_CATCH_UP;
C
cadem 已提交
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 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
      return -1;
    }
  }

  dInfo("node:%s, catched up leader, continue to process alter-node-type-request", pWrapper->name);

  taosThreadMutexLock(&pDnode->mutex);

  dInfo("node:%s, stopping node", pWrapper->name);
  dmStopNode(pWrapper);
  dInfo("node:%s, closing node", pWrapper->name);
  dmCloseNode(pWrapper);

  pWrapper = &pDnode->wrappers[ntype];
  if (taosMkDir(pWrapper->path) != 0) {
    dmReleaseWrapper(pWrapper);
    terrno = TAOS_SYSTEM_ERROR(errno);
    dError("failed to create dir:%s since %s", pWrapper->path, terrstr());
    return -1;
  }

  SMgmtInputOpt input = dmBuildMgmtInputOpt(pWrapper);

  dInfo("node:%s, start to create", pWrapper->name);
  int32_t code = (*pWrapper->func.createFp)(&input, pMsg);
  if (code != 0) {
    dError("node:%s, failed to create since %s", pWrapper->name, terrstr());
  } else {
    dInfo("node:%s, has been created", pWrapper->name);
    code = dmOpenNode(pWrapper);
    if (code == 0) {
      code = dmStartNode(pWrapper);
    }
    pWrapper->deployed = true;
    pWrapper->required = true;
  }

  taosThreadMutexUnlock(&pDnode->mutex);
  return code;
}

319
static int32_t dmProcessDropNodeReq(EDndNodeType ntype, SRpcMsg *pMsg) {
320
  SDnode *pDnode = dmInstance();
321 322 323

  SMgmtWrapper *pWrapper = dmAcquireWrapper(pDnode, ntype);
  if (pWrapper == NULL) {
324 325 326 327 328 329 330 331 332 333 334 335 336 337
    switch (ntype) {
      case MNODE:
        terrno = TSDB_CODE_MNODE_NOT_DEPLOYED;
        break;
      case QNODE:
        terrno = TSDB_CODE_QNODE_NOT_DEPLOYED;
        break;
      case SNODE:
        terrno = TSDB_CODE_SNODE_NOT_DEPLOYED;
        break;
      default:
        terrno = TSDB_CODE_APP_ERROR;
    }

338 339 340 341 342
    dError("failed to drop node since %s", terrstr());
    return -1;
  }

  taosThreadMutexLock(&pDnode->mutex);
343
  SMgmtInputOpt input = dmBuildMgmtInputOpt(pWrapper);
344

345 346
  dInfo("node:%s, start to drop", pWrapper->name);
  int32_t code = (*pWrapper->func.dropFp)(&input, pMsg);
347 348 349
  if (code != 0) {
    dError("node:%s, failed to drop since %s", pWrapper->name, terrstr());
  } else {
350
    dInfo("node:%s, has been dropped", pWrapper->name);
351 352 353 354 355 356 357
    pWrapper->required = false;
    pWrapper->deployed = false;
  }

  dmReleaseWrapper(pWrapper);

  if (code == 0) {
358
    dmStopNode(pWrapper);
359 360 361 362 363 364 365 366 367 368 369
    dmCloseNode(pWrapper);
    taosRemoveDir(pWrapper->path);
  }
  taosThreadMutexUnlock(&pDnode->mutex);
  return code;
}

SMgmtInputOpt dmBuildMgmtInputOpt(SMgmtWrapper *pWrapper) {
  SMgmtInputOpt opt = {
      .path = pWrapper->path,
      .name = pWrapper->name,
370
      .pData = &pWrapper->pDnode->data,
371
      .processCreateNodeFp = dmProcessCreateNodeReq,
C
cadem 已提交
372
      .processAlterNodeTypeFp = dmProcessAlterNodeTypeReq,
373
      .processDropNodeFp = dmProcessDropNodeReq,
S
Shengliang Guan 已提交
374 375 376
      .sendMonitorReportFp = dmSendMonitorReport,
      .getVnodeLoadsFp = dmGetVnodeLoads,
      .getMnodeLoadsFp = dmGetMnodeLoads,
D
dapan1121 已提交
377
      .getQnodeLoadsFp = dmGetQnodeLoads,
378 379
  };

380
  opt.msgCb = dmGetMsgcb(pWrapper->pDnode);
381 382 383 384
  return opt;
}

void dmReportStartup(const char *pName, const char *pDesc) {
385
  SStartupInfo *pStartup = &(dmInstance()->startup);
386 387 388
  tstrncpy(pStartup->name, pName, TSDB_STEP_NAME_LEN);
  tstrncpy(pStartup->desc, pDesc, TSDB_STEP_DESC_LEN);
  dDebug("step:%s, %s", pStartup->name, pStartup->desc);
S
shm  
Shengliang Guan 已提交
389
}
D
dapan1121 已提交
390 391

int64_t dmGetClusterId() {
S
Shengliang Guan 已提交
392
  return globalDnode.data.clusterId;
D
dapan1121 已提交
393 394
}