vnodeCommit.c 12.8 KB
Newer Older
H
refact  
Hongze Cheng 已提交
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/>.
 */

H
Hongze Cheng 已提交
16
#include "vnd.h"
H
Hongze Cheng 已提交
17
#include "vnodeInt.h"
H
Hongze Cheng 已提交
18

H
Hongze Cheng 已提交
19 20
#define VND_INFO_FNAME_TMP "vnode_tmp.json"

H
Hongze Cheng 已提交
21 22
static int vnodeEncodeInfo(const SVnodeInfo *pInfo, char **ppData);
static int vnodeCommitImpl(SCommitInfo *pInfo);
H
refact  
Hongze Cheng 已提交
23

H
Hongze Cheng 已提交
24 25
#define WAIT_TIME_MILI_SEC 50

H
Hongze Cheng 已提交
26
int vnodeBegin(SVnode *pVnode) {
H
Hongze Cheng 已提交
27
  // alloc buffer pool
H
Hongze Cheng 已提交
28 29
  int32_t nTry = 0;

H
Hongze Cheng 已提交
30
  taosThreadMutexLock(&pVnode->mutex);
H
Hongze Cheng 已提交
31 32

  while (pVnode->pPool == NULL) {
H
Hongze Cheng 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
    vInfo("vgId:%d no free buffer pool on %d try, wait %d ms...", TD_VID(pVnode), ++nTry, WAIT_TIME_MILI_SEC);

    struct timeval  tv;
    struct timespec ts;
    taosGetTimeOfDay(&tv);
    ts.tv_nsec = tv.tv_usec * 1000 + WAIT_TIME_MILI_SEC * 1000000;
    if (ts.tv_nsec > 999999999l) {
      ts.tv_sec = tv.tv_sec + 1;
      ts.tv_nsec -= 1000000000l;
    } else {
      ts.tv_sec = tv.tv_sec;
    }

    int32_t rc = taosThreadCondTimedWait(&pVnode->poolNotEmpty, &pVnode->mutex, &ts);
    if (rc && rc != ETIMEDOUT) {
      terrno = TAOS_SYSTEM_ERROR(rc);
      taosThreadMutexUnlock(&pVnode->mutex);
      return -1;
    }
H
Hongze Cheng 已提交
52 53 54
  }

  pVnode->inUse = pVnode->pPool;
H
Hongze Cheng 已提交
55
  pVnode->inUse->nRef = 1;
H
Hongze Cheng 已提交
56 57 58
  pVnode->pPool = pVnode->inUse->next;
  pVnode->inUse->next = NULL;

H
Hongze Cheng 已提交
59
  taosThreadMutexUnlock(&pVnode->mutex);
H
Hongze Cheng 已提交
60

H
Hongze Cheng 已提交
61
  pVnode->state.commitID++;
H
Hongze Cheng 已提交
62
  // begin meta
63
  if (metaBegin(pVnode->pMeta, META_BEGIN_HEAP_BUFFERPOOL) < 0) {
S
Shengliang Guan 已提交
64
    vError("vgId:%d, failed to begin meta since %s", TD_VID(pVnode), tstrerror(terrno));
H
Hongze Cheng 已提交
65 66 67 68
    return -1;
  }

  // begin tsdb
H
Hongze Cheng 已提交
69 70 71 72
  if (tsdbBegin(pVnode->pTsdb) < 0) {
    vError("vgId:%d, failed to begin tsdb since %s", TD_VID(pVnode), tstrerror(terrno));
    return -1;
  }
C
Cary Xu 已提交
73

C
Cary Xu 已提交
74
  // begin sma
C
Cary Xu 已提交
75
  if (VND_IS_RSMA(pVnode) && smaBegin(pVnode->pSma) < 0) {
C
Cary Xu 已提交
76 77 78
    vError("vgId:%d, failed to begin sma since %s", TD_VID(pVnode), tstrerror(terrno));
    return -1;
  }
C
Cary Xu 已提交
79

H
Hongze Cheng 已提交
80 81 82
  return 0;
}

83 84 85
void vnodeUpdCommitSched(SVnode *pVnode) {
  int64_t randNum = taosRand();
  pVnode->commitSched.commitMs = taosGetMonoTimestampMs();
86
  pVnode->commitSched.maxWaitMs = tsVndCommitMaxIntervalMs + (randNum % tsVndCommitMaxIntervalMs);
87 88
}

C
Cary Xu 已提交
89
int vnodeShouldCommit(SVnode *pVnode) {
B
Benguang Zhao 已提交
90 91 92 93
  if (!pVnode->inUse || !osDataSpaceAvailable()) {
    return false;
  }

94
  SVCommitSched *pSched = &pVnode->commitSched;
H
Hongze Cheng 已提交
95
  int64_t        nowMs = taosGetMonoTimestampMs();
B
Benguang Zhao 已提交
96

97 98
  return (((pVnode->inUse->size > pVnode->inUse->node.size) && (pSched->commitMs + SYNC_VND_COMMIT_MIN_MS < nowMs)) ||
          (pVnode->inUse->size > 0 && pSched->commitMs + pSched->maxWaitMs < nowMs));
B
Benguang Zhao 已提交
99 100 101
}

int vnodeShouldCommitOld(SVnode *pVnode) {
C
Cary Xu 已提交
102
  if (pVnode->inUse) {
103
    return osDataSpaceAvailable() && (pVnode->inUse->size > pVnode->inUse->node.size);
C
Cary Xu 已提交
104 105 106
  }
  return false;
}
H
Hongze Cheng 已提交
107

H
Hongze Cheng 已提交
108 109 110
int vnodeSaveInfo(const char *dir, const SVnodeInfo *pInfo) {
  char      fname[TSDB_FILENAME_LEN];
  TdFilePtr pFile;
H
Hongze Cheng 已提交
111
  char     *data;
H
Hongze Cheng 已提交
112 113 114 115 116 117

  snprintf(fname, TSDB_FILENAME_LEN, "%s%s%s", dir, TD_DIRSEP, VND_INFO_FNAME_TMP);

  // encode info
  data = NULL;

H
Hongze Cheng 已提交
118
  if (vnodeEncodeInfo(pInfo, &data) < 0) {
119
    vError("failed to encode json info.");
H
Hongze Cheng 已提交
120 121 122 123 124 125
    return -1;
  }

  // save info to a vnode_tmp.json
  pFile = taosOpenFile(fname, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
  if (pFile == NULL) {
S
Shengliang Guan 已提交
126
    vError("failed to open info file:%s for write:%s", fname, terrstr());
H
Hongze Cheng 已提交
127 128 129 130
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }

H
Hongze Cheng 已提交
131
  if (taosWriteFile(pFile, data, strlen(data)) < 0) {
132
    vError("failed to write info file:%s error:%s", fname, terrstr());
H
Hongze Cheng 已提交
133 134 135 136 137
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

  if (taosFsyncFile(pFile) < 0) {
S
Shengliang Guan 已提交
138
    vError("failed to fsync info file:%s error:%s", fname, terrstr());
H
Hongze Cheng 已提交
139 140 141 142 143 144 145 146 147
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

  taosCloseFile(&pFile);

  // free info binary
  taosMemoryFree(data);

148 149
  vInfo("vgId:%d, vnode info is saved, fname:%s replica:%d selfIndex:%d", pInfo->config.vgId, fname,
        pInfo->config.syncCfg.replicaNum, pInfo->config.syncCfg.myIndex);
H
Hongze Cheng 已提交
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170

  return 0;

_err:
  taosCloseFile(&pFile);
  taosMemoryFree(data);
  return -1;
}

int vnodeCommitInfo(const char *dir, const SVnodeInfo *pInfo) {
  char fname[TSDB_FILENAME_LEN];
  char tfname[TSDB_FILENAME_LEN];

  snprintf(fname, TSDB_FILENAME_LEN, "%s%s%s", dir, TD_DIRSEP, VND_INFO_FNAME);
  snprintf(tfname, TSDB_FILENAME_LEN, "%s%s%s", dir, TD_DIRSEP, VND_INFO_FNAME_TMP);

  if (taosRenameFile(tfname, fname) < 0) {
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }

S
Shengliang Guan 已提交
171
  vInfo("vgId:%d, vnode info is committed", pInfo->config.vgId);
H
Hongze Cheng 已提交
172 173 174 175

  return 0;
}

H
Hongze Cheng 已提交
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
int vnodeLoadInfo(const char *dir, SVnodeInfo *pInfo) {
  char      fname[TSDB_FILENAME_LEN];
  TdFilePtr pFile = NULL;
  char     *pData = NULL;
  int64_t   size;

  snprintf(fname, TSDB_FILENAME_LEN, "%s%s%s", dir, TD_DIRSEP, VND_INFO_FNAME);

  // read info
  pFile = taosOpenFile(fname, TD_FILE_READ);
  if (pFile == NULL) {
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }

  if (taosFStatFile(pFile, &size, NULL) < 0) {
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

H
Hongze Cheng 已提交
196
  pData = taosMemoryMalloc(size + 1);
H
Hongze Cheng 已提交
197 198 199 200 201 202 203 204 205 206
  if (pData == NULL) {
    terrno = TSDB_CODE_OUT_OF_MEMORY;
    goto _err;
  }

  if (taosReadFile(pFile, pData, size) < 0) {
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

H
Hongze Cheng 已提交
207 208
  pData[size] = '\0';

H
Hongze Cheng 已提交
209 210 211 212 213 214 215 216 217 218
  taosCloseFile(&pFile);

  // decode info
  if (vnodeDecodeInfo(pData, pInfo) < 0) {
    taosMemoryFree(pData);
    return -1;
  }

  taosMemoryFree(pData);

H
Hongze Cheng 已提交
219
  return 0;
H
Hongze Cheng 已提交
220 221 222 223 224

_err:
  taosCloseFile(&pFile);
  taosMemoryFree(pData);
  return -1;
H
Hongze Cheng 已提交
225 226
}

227 228 229 230 231
static int32_t vnodePrepareCommit(SVnode *pVnode, SCommitInfo *pInfo) {
  int32_t code = 0;
  int32_t lino = 0;
  char    dir[TSDB_FILENAME_LEN] = {0};

H
Hongze Cheng 已提交
232 233
  tsem_wait(&pVnode->canCommit);

234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
  pVnode->state.commitTerm = pVnode->state.applyTerm;

  pInfo->info.config = pVnode->config;
  pInfo->info.state.committed = pVnode->state.applied;
  pInfo->info.state.commitTerm = pVnode->state.applyTerm;
  pInfo->info.state.commitID = pVnode->state.commitID;
  pInfo->pVnode = pVnode;
  pInfo->txn = metaGetTxn(pVnode->pMeta);

  // save info
  if (pVnode->pTfs) {
    snprintf(dir, TSDB_FILENAME_LEN, "%s%s%s", tfsGetPrimaryPath(pVnode->pTfs), TD_DIRSEP, pVnode->path);
  } else {
    snprintf(dir, TSDB_FILENAME_LEN, "%s", pVnode->path);
  }
249 250

  vDebug("vgId:%d, save config while prepare commit", TD_VID(pVnode));
251 252 253 254 255
  if (vnodeSaveInfo(dir, &pInfo->info) < 0) {
    code = terrno;
    TSDB_CHECK_CODE(code, lino, _exit);
  }

256
  tsdbPrepareCommit(pVnode->pTsdb);
K
kailixu 已提交
257 258
  smaPrepareAsyncCommit(pVnode->pSma);

259 260
  metaPrepareAsyncCommit(pVnode->pMeta);

H
Hongze Cheng 已提交
261 262
  vnodeBufPoolUnRef(pVnode->inUse);
  pVnode->inUse = NULL;
263 264 265 266 267 268 269 270 271

_exit:
  if (code) {
    vError("vgId:%d, %s failed at line %d since %s, commit id:%" PRId64, TD_VID(pVnode), __func__, lino,
           tstrerror(code), pVnode->state.commitID);
  } else {
    vDebug("vgId:%d, %s done", TD_VID(pVnode), __func__);
  }
  return code;
H
Hongze Cheng 已提交
272
}
273

H
Hongze Cheng 已提交
274 275 276
static int32_t vnodeCommitTask(void *arg) {
  int32_t code = 0;

H
Hongze Cheng 已提交
277
  SCommitInfo *pInfo = (SCommitInfo *)arg;
H
Hongze Cheng 已提交
278

H
Hongze Cheng 已提交
279 280
  // commit
  code = vnodeCommitImpl(pInfo);
H
Hongze Cheng 已提交
281 282
  if (code) goto _exit;

H
Hongze Cheng 已提交
283 284
  // end commit
  tsem_post(&pInfo->pVnode->canCommit);
H
Hongze Cheng 已提交
285 286

_exit:
H
Hongze Cheng 已提交
287
  taosMemoryFree(pInfo);
H
Hongze Cheng 已提交
288 289
  return code;
}
B
Benguang Zhao 已提交
290

H
refact  
Hongze Cheng 已提交
291
int vnodeAsyncCommit(SVnode *pVnode) {
H
Hongze Cheng 已提交
292
  int32_t code = 0;
H
Hongze Cheng 已提交
293

H
Hongze Cheng 已提交
294
  SCommitInfo *pInfo = (SCommitInfo *)taosMemoryCalloc(1, sizeof(*pInfo));
H
Hongze Cheng 已提交
295 296 297 298
  if (NULL == pInfo) {
    code = TSDB_CODE_OUT_OF_MEMORY;
    goto _exit;
  }
299 300 301 302 303 304 305 306

  // prepare to commit
  code = vnodePrepareCommit(pVnode, pInfo);
  if (TSDB_CODE_SUCCESS != code) {
    goto _exit;
  }

  // schedule the task
H
Hongze Cheng 已提交
307
  vnodeScheduleTask(vnodeCommitTask, pInfo);
H
Hongze Cheng 已提交
308

H
Hongze Cheng 已提交
309 310
_exit:
  if (code) {
311 312 313
    if (NULL != pInfo) {
      taosMemoryFree(pInfo);
    }
314
    vError("vgId:%d, vnode async commit failed since %s, commitId:%" PRId64, TD_VID(pVnode), tstrerror(code),
H
Hongze Cheng 已提交
315 316
           pVnode->state.commitID);
  } else {
317 318
    vInfo("vgId:%d, vnode async commit done, commitId:%" PRId64 " term:%" PRId64 " applied:%" PRId64, TD_VID(pVnode),
          pVnode->state.commitID, pVnode->state.applyTerm, pVnode->state.applied);
H
Hongze Cheng 已提交
319 320
  }
  return code;
H
Hongze Cheng 已提交
321
}
H
refact  
Hongze Cheng 已提交
322

H
Hongze Cheng 已提交
323 324
int vnodeSyncCommit(SVnode *pVnode) {
  vnodeAsyncCommit(pVnode);
H
Hongze Cheng 已提交
325 326
  tsem_wait(&pVnode->canCommit);
  tsem_post(&pVnode->canCommit);
H
Hongze Cheng 已提交
327 328 329
  return 0;
}

H
Hongze Cheng 已提交
330 331 332 333 334 335
static int vnodeCommitImpl(SCommitInfo *pInfo) {
  int32_t code = 0;
  int32_t lino = 0;

  char    dir[TSDB_FILENAME_LEN] = {0};
  SVnode *pVnode = pInfo->pVnode;
H
Hongze Cheng 已提交
336

337
  vInfo("vgId:%d, start to commit, commitId:%" PRId64 " version:%" PRId64 " term: %" PRId64, TD_VID(pVnode),
B
Benguang Zhao 已提交
338 339
        pInfo->info.state.commitID, pInfo->info.state.committed, pInfo->info.state.commitTerm);

340
  vnodeUpdCommitSched(pVnode);
H
Hongze Cheng 已提交
341

342 343 344 345 346 347
  // persist wal before starting
  if (walPersist(pVnode->pWal) < 0) {
    vError("vgId:%d, failed to persist wal since %s", TD_VID(pVnode), terrstr());
    return -1;
  }

H
Hongze Cheng 已提交
348 349 350 351 352
  if (pVnode->pTfs) {
    snprintf(dir, TSDB_FILENAME_LEN, "%s%s%s", tfsGetPrimaryPath(pVnode->pTfs), TD_DIRSEP, pVnode->path);
  } else {
    snprintf(dir, TSDB_FILENAME_LEN, "%s", pVnode->path);
  }
353

354
  syncBeginSnapshot(pVnode->sync, pInfo->info.state.committed);
H
Hongze Cheng 已提交
355 356

  // commit each sub-system
H
Hongze Cheng 已提交
357
  code = tsdbCommit(pVnode->pTsdb, pInfo);
C
Cary Xu 已提交
358 359
  TSDB_CHECK_CODE(code, lino, _exit);

C
Cary Xu 已提交
360
  if (VND_IS_RSMA(pVnode)) {
H
Hongze Cheng 已提交
361
    code = smaCommit(pVnode->pSma, pInfo);
H
Hongze Cheng 已提交
362
    TSDB_CHECK_CODE(code, lino, _exit);
H
Hongze Cheng 已提交
363
  }
C
Cary Xu 已提交
364

H
Hongze Cheng 已提交
365
  if (tqCommit(pVnode->pTq) < 0) {
H
Hongze Cheng 已提交
366 367
    code = TSDB_CODE_FAILED;
    TSDB_CHECK_CODE(code, lino, _exit);
H
Hongze Cheng 已提交
368 369 370
  }

  // commit info
H
Hongze Cheng 已提交
371
  if (vnodeCommitInfo(dir, &pInfo->info) < 0) {
H
Hongze Cheng 已提交
372 373
    code = terrno;
    TSDB_CHECK_CODE(code, lino, _exit);
H
Hongze Cheng 已提交
374
  }
H
Hongze Cheng 已提交
375

C
Cary Xu 已提交
376 377 378
  code = tsdbFinishCommit(pVnode->pTsdb);
  TSDB_CHECK_CODE(code, lino, _exit);

C
Cary Xu 已提交
379 380 381 382
  if (VND_IS_RSMA(pVnode)) {
    code = smaFinishCommit(pVnode->pSma);
    TSDB_CHECK_CODE(code, lino, _exit);
  }
H
Hongze Cheng 已提交
383

384
  if (metaFinishCommit(pVnode->pMeta, pInfo->txn) < 0) {
385 386 387 388
    code = terrno;
    TSDB_CHECK_CODE(code, lino, _exit);
  }

H
Hongze Cheng 已提交
389
  pVnode->state.committed = pInfo->info.state.committed;
H
Hongze Cheng 已提交
390

C
Cary Xu 已提交
391 392
  if (smaPostCommit(pVnode->pSma) < 0) {
    vError("vgId:%d, failed to post-commit sma since %s", TD_VID(pVnode), tstrerror(terrno));
C
Cary Xu 已提交
393 394
    return -1;
  }
H
Hongze Cheng 已提交
395

396
  syncEndSnapshot(pVnode->sync);
H
Hongze Cheng 已提交
397

H
Hongze Cheng 已提交
398 399
_exit:
  if (code) {
S
Shengliang Guan 已提交
400
    vError("vgId:%d, %s failed at line %d since %s", TD_VID(pVnode), __func__, lino, tstrerror(code));
H
Hongze Cheng 已提交
401 402 403
  } else {
    vInfo("vgId:%d, commit end", TD_VID(pVnode));
  }
H
Hongze Cheng 已提交
404 405 406
  return 0;
}

H
Hongze Cheng 已提交
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
bool vnodeShouldRollback(SVnode *pVnode) {
  char tFName[TSDB_FILENAME_LEN] = {0};
  snprintf(tFName, TSDB_FILENAME_LEN, "%s%s%s%s%s", tfsGetPrimaryPath(pVnode->pTfs), TD_DIRSEP, pVnode->path, TD_DIRSEP,
           VND_INFO_FNAME_TMP);

  return taosCheckExistFile(tFName);
}

void vnodeRollback(SVnode *pVnode) {
  char tFName[TSDB_FILENAME_LEN] = {0};
  snprintf(tFName, TSDB_FILENAME_LEN, "%s%s%s%s%s", tfsGetPrimaryPath(pVnode->pTfs), TD_DIRSEP, pVnode->path, TD_DIRSEP,
           VND_INFO_FNAME_TMP);

  (void)taosRemoveFile(tFName);
}

H
Hongze Cheng 已提交
423 424 425 426
static int vnodeEncodeState(const void *pObj, SJson *pJson) {
  const SVState *pState = (SVState *)pObj;

  if (tjsonAddIntegerToObject(pJson, "commit version", pState->committed) < 0) return -1;
H
Hongze Cheng 已提交
427
  if (tjsonAddIntegerToObject(pJson, "commit ID", pState->commitID) < 0) return -1;
H
Hongze Cheng 已提交
428
  if (tjsonAddIntegerToObject(pJson, "commit term", pState->commitTerm) < 0) return -1;
H
Hongze Cheng 已提交
429 430 431 432 433 434 435

  return 0;
}

static int vnodeDecodeState(const SJson *pJson, void *pObj) {
  SVState *pState = (SVState *)pObj;

436 437
  int32_t code;
  tjsonGetNumberValue(pJson, "commit version", pState->committed, code);
H
Hongze Cheng 已提交
438
  if (code < 0) return -1;
H
Hongze Cheng 已提交
439 440
  tjsonGetNumberValue(pJson, "commit ID", pState->commitID, code);
  if (code < 0) return -1;
H
Hongze Cheng 已提交
441 442
  tjsonGetNumberValue(pJson, "commit term", pState->commitTerm, code);
  if (code < 0) return -1;
H
Hongze Cheng 已提交
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473

  return 0;
}

static int vnodeEncodeInfo(const SVnodeInfo *pInfo, char **ppData) {
  SJson *pJson;
  char  *pData;

  *ppData = NULL;

  pJson = tjsonCreateObject();
  if (pJson == NULL) {
    return -1;
  }

  if (tjsonAddObject(pJson, "config", vnodeEncodeConfig, (void *)&pInfo->config) < 0) {
    goto _err;
  }

  if (tjsonAddObject(pJson, "state", vnodeEncodeState, (void *)&pInfo->state) < 0) {
    goto _err;
  }

  pData = tjsonToString(pJson);
  if (pData == NULL) {
    goto _err;
  }

  tjsonDelete(pJson);

  *ppData = pData;
H
Hongze Cheng 已提交
474
  return 0;
H
Hongze Cheng 已提交
475 476 477 478

_err:
  tjsonDelete(pJson);
  return -1;
H
Hongze Cheng 已提交
479 480
}

H
Hongze Cheng 已提交
481
int vnodeDecodeInfo(uint8_t *pData, SVnodeInfo *pInfo) {
H
Hongze Cheng 已提交
482 483
  SJson *pJson = NULL;

H
fix bug  
Hongze Cheng 已提交
484
  pJson = tjsonParse(pData);
H
Hongze Cheng 已提交
485 486 487 488 489 490 491 492 493 494 495 496 497 498
  if (pJson == NULL) {
    return -1;
  }

  if (tjsonToObject(pJson, "config", vnodeDecodeConfig, (void *)&pInfo->config) < 0) {
    goto _err;
  }

  if (tjsonToObject(pJson, "state", vnodeDecodeState, (void *)&pInfo->state) < 0) {
    goto _err;
  }

  tjsonDelete(pJson);

H
Hongze Cheng 已提交
499
  return 0;
H
Hongze Cheng 已提交
500 501 502 503

_err:
  tjsonDelete(pJson);
  return -1;
H
Hongze Cheng 已提交
504
}