dmEnv.c 11.3 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
extern char   tsVersionName[16];
S
Shengliang Guan 已提交
20
static SDnode globalDnode = {0};
21

S
Shengliang Guan 已提交
22
SDnode *dmInstance() { return &globalDnode; }
23 24 25

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 已提交
26
    dError("env is already initialized");
S
shm  
Shengliang Guan 已提交
27 28 29
    terrno = TSDB_CODE_REPEAT_INIT;
    return -1;
  }
30 31
  return 0;
}
S
shm  
Shengliang Guan 已提交
32

33
static int32_t dmInitSystem() {
S
shm  
Shengliang Guan 已提交
34 35 36
  taosIgnSIGPIPE();
  taosBlockSIGPIPE();
  taosResolveCRC();
37 38
  return 0;
}
S
shm  
Shengliang Guan 已提交
39

K
kailixu 已提交
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
#define STR_CASE_CMP(s, d)   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 DM_INIT_CODE()                                   \
  do {                                                   \
    code = (int32_t)((2147483648 | ((0) << 7 | (298)))); \
    strncpy(stName, tsVersionName, 64);                  \
  } while (0)

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

55
static int32_t dmInitMonitor() {
K
kailixu 已提交
56
  int32_t code = 0;
S
Shengliang 已提交
57
  SMonCfg monCfg = {0};
K
kailixu 已提交
58 59 60 61 62
  char    reName[64] = {0};
  char    stName[64] = {0};
  char    ver[64] = {0};

  DM_INIT_CODE();
S
Shengliang 已提交
63 64 65 66 67
  monCfg.maxLogs = tsMonitorMaxLogs;
  monCfg.port = tsMonitorPort;
  monCfg.server = tsMonitorFqdn;
  monCfg.comp = tsMonitorComp;
  if (monInit(&monCfg) != 0) {
K
kailixu 已提交
68 69
    if (terrno != 0) code = terrno;
    goto _exit;
S
Shengliang 已提交
70
  }
K
kailixu 已提交
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
  
  if (STR_STR_CMP(stName, "ia")) {
    DM_ERR_RTN(0);
  }

  if (taosGetOsReleaseName(reName, stName, ver, 64) != 0) {
    goto _exit;
  }

 else if (STR_CASE_CMP(stName, "Ubuntu")) {
    if (STR_INT_CMP(ver, 17, >)) {
      DM_ERR_RTN(0);
    }
  } else if (STR_CASE_CMP(stName, "CentOS Linux")) {
    if (STR_INT_CMP(ver, 6, >)) {
      DM_ERR_RTN(0);
    }
  } else if (STR_STR_CMP(stName, "Red Hat") || STR_STR_CMP(stName, "Debian GNU") || STR_STR_CMP(stName, "CoreOS") ||
             STR_STR_CMP(stName, "FreeBSD") || STR_STR_CMP(stName, "openSUSE") || STR_STR_CMP(stName, "SLES") ||
             STR_STR_CMP(stName, "Fedora") || STR_STR_CMP(stName, "MacOS")) {
    DM_ERR_RTN(0);
  }

_exit:
  if (code != 0) {
    dError("failed to init monitor since %d", code);
  }
  return code;
99 100
}

wafwerar's avatar
wafwerar 已提交
101 102
static bool dmCheckDiskSpace() {
  osUpdate();
103
  // sufficiency
104
  if (!osDataSpaceSufficient()) {
105 106 107
    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 已提交
108
  }
109
  if (!osLogSpaceSufficient()) {
110 111 112
    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 已提交
113
  }
114
  if (!osTempSpaceSufficient()) {
115 116 117
    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 已提交
118
  }
119 120 121 122
  // availability
  bool ret = true;
  if (!osDataSpaceAvailable()) {
    dError("data disk space unavailable, i.e. %s", tsDataDir);
123
    terrno = TSDB_CODE_NO_DISKSPACE;
124 125 126 127
    ret = false;
  }
  if (!osLogSpaceAvailable()) {
    dError("log disk space unavailable, i.e. %s", tsLogDir);
128
    terrno = TSDB_CODE_NO_DISKSPACE;
129 130 131 132
    ret = false;
  }
  if (!osTempSpaceAvailable()) {
    dError("temp disk space unavailable, i.e. %s", tsTempDir);
133
    terrno = TSDB_CODE_NO_DISKSPACE;
134 135 136
    ret = false;
  }
  return ret;
wafwerar's avatar
wafwerar 已提交
137 138 139
}

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

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

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

163 164
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 已提交
165
    dError("dnode env is already cleaned up");
166
    return -1;
S
shm  
Shengliang Guan 已提交
167
  }
168 169 170 171
  return 0;
}

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

  taosCleanupCfg();
185
  taosCloseLog();
186 187 188
}

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

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

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

  SMgmtWrapper *pWrapper = dmAcquireWrapper(pDnode, ntype);
  if (pWrapper != NULL) {
    dmReleaseWrapper(pWrapper);
204 205 206 207 208 209 210 211 212 213 214 215 216
    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;
    }
217 218 219 220
    dError("failed to create node since %s", terrstr());
    return -1;
  }

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

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

231
  taosThreadMutexLock(&pDnode->mutex);
232 233
  SMgmtInputOpt input = dmBuildMgmtInputOpt(pWrapper);

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

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

C
cadem 已提交
252 253 254 255 256 257 258 259 260 261 262 263 264 265
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 已提交
266 267 268 269
  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 已提交
270
      dError("node:%s, failed to alter node type since node already is role:%d", pWrapper->name, role);
C
cadem 已提交
271 272 273 274 275
      terrno = TSDB_CODE_MNODE_ALREADY_IS_VOTER;
      return -1;
    }
  }

C
cadem 已提交
276 277
  if(pWrapper->func.isCatchUpFp != NULL){
    dInfo("node:%s, checking node catch up", pWrapper->name);
C
cadem 已提交
278 279
    if((*pWrapper->func.isCatchUpFp)(pWrapper->pMgmt) != 1){
      terrno = TSDB_CODE_MNODE_NOT_CATCH_UP;
C
cadem 已提交
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 319 320
      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;
}

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

  SMgmtWrapper *pWrapper = dmAcquireWrapper(pDnode, ntype);
  if (pWrapper == NULL) {
326 327 328 329 330 331 332 333 334 335 336 337 338 339
    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;
    }

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

  taosThreadMutexLock(&pDnode->mutex);
345
  SMgmtInputOpt input = dmBuildMgmtInputOpt(pWrapper);
346

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

  dmReleaseWrapper(pWrapper);

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

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

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

void dmReportStartup(const char *pName, const char *pDesc) {
387
  SStartupInfo *pStartup = &(dmInstance()->startup);
388 389 390
  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 已提交
391
}
D
dapan1121 已提交
392 393

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