mndSync.c 11.8 KB
Newer Older
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
#include "mndSync.h"
18
#include "mndTrans.h"
19

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
static int32_t mndSyncEqCtrlMsg(const SMsgCb *msgcb, SRpcMsg *pMsg) {
  if (pMsg == NULL || pMsg->pCont == NULL) {
    return -1;
  }

  SMsgHead *pHead = pMsg->pCont;
  pHead->contLen = htonl(pHead->contLen);
  pHead->vgId = htonl(pHead->vgId);

  if (msgcb == NULL || msgcb->putToQueueFp == NULL) {
    rpcFreeCont(pMsg->pCont);
    pMsg->pCont = NULL;
    return -1;
  }

  int32_t code = tmsgPutToQueue(msgcb, SYNC_CTRL_QUEUE, pMsg);
  if (code != 0) {
    rpcFreeCont(pMsg->pCont);
    pMsg->pCont = NULL;
  }
  return code;
}

43
static int32_t mndSyncEqMsg(const SMsgCb *msgcb, SRpcMsg *pMsg) {
44 45 46 47
  if (pMsg == NULL || pMsg->pCont == NULL) {
    return -1;
  }

M
Minghao Li 已提交
48 49 50 51
  SMsgHead *pHead = pMsg->pCont;
  pHead->contLen = htonl(pHead->contLen);
  pHead->vgId = htonl(pHead->vgId);

52 53 54 55 56 57
  if (msgcb == NULL || msgcb->putToQueueFp == NULL) {
    rpcFreeCont(pMsg->pCont);
    pMsg->pCont = NULL;
    return -1;
  }

58 59 60 61 62 63
  int32_t code = tmsgPutToQueue(msgcb, SYNC_QUEUE, pMsg);
  if (code != 0) {
    rpcFreeCont(pMsg->pCont);
    pMsg->pCont = NULL;
  }
  return code;
M
Minghao Li 已提交
64
}
M
Minghao Li 已提交
65

66 67 68 69 70 71 72 73
static int32_t mndSyncSendMsg(const SEpSet *pEpSet, SRpcMsg *pMsg) {
  int32_t code = tmsgSendReq(pEpSet, pMsg);
  if (code != 0) {
    rpcFreeCont(pMsg->pCont);
    pMsg->pCont = NULL;
  }
  return code;
}
M
Minghao Li 已提交
74

S
Shengliang Guan 已提交
75
void mndSyncCommitMsg(const SSyncFSM *pFsm, const SRpcMsg *pMsg, const SFsmCbMeta *pMeta) {
S
Shengliang Guan 已提交
76 77 78 79
  SMnode    *pMnode = pFsm->data;
  SSyncMgmt *pMgmt = &pMnode->syncMgmt;
  SSdbRaw   *pRaw = pMsg->pCont;

80 81
  // delete msg handle
  SRpcMsg rpcMsg = {0};
S
Shengliang Guan 已提交
82
  rpcMsg.info = pMsg->info;
83

S
Shengliang Guan 已提交
84
  int32_t transId = sdbGetIdFromRaw(pMnode->pSdb, pRaw);
S
Shengliang Guan 已提交
85
  pMgmt->errCode = pMeta->code;
86
  mInfo("trans:%d, is proposed, saved:%d code:0x%x, apply index:%" PRId64 " term:%" PRIu64 " config:%" PRId64
H
Hongze Cheng 已提交
87
        " role:%s raw:%p",
S
Shengliang Guan 已提交
88
        transId, pMgmt->transId, pMeta->code, pMeta->index, pMeta->term, pMeta->lastConfigIndex, syncStr(pMeta->state),
H
Hongze Cheng 已提交
89
        pRaw);
S
Shengliang Guan 已提交
90 91 92

  if (pMgmt->errCode == 0) {
    sdbWriteWithoutFree(pMnode->pSdb, pRaw);
S
Shengliang Guan 已提交
93
    sdbSetApplyInfo(pMnode->pSdb, pMeta->index, pMeta->term, pMeta->lastConfigIndex);
S
Shengliang Guan 已提交
94 95
  }

96
  taosWLockLatch(&pMgmt->lock);
97
  if (transId <= 0) {
98
    taosWUnLockLatch(&pMgmt->lock);
99 100
    mError("trans:%d, invalid commit msg", transId);
  } else if (transId == pMgmt->transId) {
S
Shengliang Guan 已提交
101
    if (pMgmt->errCode != 0) {
102 103
      mError("trans:%d, failed to propose since %s, post sem", transId, tstrerror(pMgmt->errCode));
    } else {
S
Shengliang Guan 已提交
104
      mInfo("trans:%d, is proposed and post sem", transId);
S
Shengliang Guan 已提交
105
    }
S
Shengliang Guan 已提交
106
    pMgmt->transId = 0;
S
Shengliang Guan 已提交
107
    tsem_post(&pMgmt->syncSem);
108
    taosWUnLockLatch(&pMgmt->lock);
109
  } else {
110
    taosWUnLockLatch(&pMgmt->lock);
111 112
    STrans *pTrans = mndAcquireTrans(pMnode, transId);
    if (pTrans != NULL) {
113
      mInfo("trans:%d, execute in mnode which not leader", transId);
114 115
      mndTransExecute(pMnode, pTrans);
      mndReleaseTrans(pMnode, pTrans);
116 117 118
      // sdbWriteFile(pMnode->pSdb, SDB_WRITE_DELTA);
    } else {
      mError("trans:%d, not found while execute in mnode since %s", transId, terrstr());
119
    }
M
Minghao Li 已提交
120 121 122
  }
}

S
Shengliang Guan 已提交
123
int32_t mndSyncGetSnapshot(const SSyncFSM *pFsm, SSnapshot *pSnapshot, void *pReaderParam, void **ppReader) {
124
  mInfo("start to read snapshot from sdb in atomic way");
125 126 127
  SMnode *pMnode = pFsm->data;
  return sdbStartRead(pMnode->pSdb, (SSdbIter **)ppReader, &pSnapshot->lastApplyIndex, &pSnapshot->lastApplyTerm,
                      &pSnapshot->lastConfigIndex);
128 129 130
  return 0;
}

S
Shengliang Guan 已提交
131
int32_t mndSyncGetSnapshotInfo(const SSyncFSM *pFsm, SSnapshot *pSnapshot) {
132
  SMnode *pMnode = pFsm->data;
133
  sdbGetCommitInfo(pMnode->pSdb, &pSnapshot->lastApplyIndex, &pSnapshot->lastApplyTerm, &pSnapshot->lastConfigIndex);
M
Minghao Li 已提交
134 135 136
  return 0;
}

S
Shengliang Guan 已提交
137
void mndRestoreFinish(const SSyncFSM *pFsm) {
138
  SMnode *pMnode = pFsm->data;
S
Shengliang Guan 已提交
139

S
Shengliang Guan 已提交
140
  if (!pMnode->deploy) {
141
    mInfo("vgId:1, sync restore finished, and will handle outstanding transactions");
S
Shengliang Guan 已提交
142
    mndTransPullup(pMnode);
143
    mndSetRestored(pMnode, true);
S
Shengliang Guan 已提交
144
  } else {
145
    mInfo("vgId:1, sync restore finished");
S
Shengliang Guan 已提交
146
  }
147 148
}

S
Shengliang Guan 已提交
149
int32_t mndSnapshotStartRead(const SSyncFSM *pFsm, void *pParam, void **ppReader) {
150
  mInfo("start to read snapshot from sdb");
S
Shengliang Guan 已提交
151
  SMnode *pMnode = pFsm->data;
152
  return sdbStartRead(pMnode->pSdb, (SSdbIter **)ppReader, NULL, NULL, NULL);
S
Shengliang Guan 已提交
153 154
}

S
Shengliang Guan 已提交
155
int32_t mndSnapshotStopRead(const SSyncFSM *pFsm, void *pReader) {
156
  mInfo("stop to read snapshot from sdb");
S
Shengliang Guan 已提交
157 158 159 160
  SMnode *pMnode = pFsm->data;
  return sdbStopRead(pMnode->pSdb, pReader);
}

S
Shengliang Guan 已提交
161
int32_t mndSnapshotDoRead(const SSyncFSM *pFsm, void *pReader, void **ppBuf, int32_t *len) {
S
Shengliang Guan 已提交
162 163 164 165
  SMnode *pMnode = pFsm->data;
  return sdbDoRead(pMnode->pSdb, pReader, ppBuf, len);
}

S
Shengliang Guan 已提交
166
int32_t mndSnapshotStartWrite(const SSyncFSM *pFsm, void *pParam, void **ppWriter) {
S
Shengliang Guan 已提交
167 168 169 170 171
  mInfo("start to apply snapshot to sdb");
  SMnode *pMnode = pFsm->data;
  return sdbStartWrite(pMnode->pSdb, (SSdbIter **)ppWriter);
}

S
Shengliang Guan 已提交
172
int32_t mndSnapshotStopWrite(const SSyncFSM *pFsm, void *pWriter, bool isApply, SSnapshot *pSnapshot) {
173
  mInfo("stop to apply snapshot to sdb, apply:%d, index:%" PRId64 " term:%" PRIu64 " config:%" PRId64, isApply,
S
Shengliang Guan 已提交
174
        pSnapshot->lastApplyIndex, pSnapshot->lastApplyTerm, pSnapshot->lastConfigIndex);
S
Shengliang Guan 已提交
175
  SMnode *pMnode = pFsm->data;
176 177
  return sdbStopWrite(pMnode->pSdb, pWriter, isApply, pSnapshot->lastApplyIndex, pSnapshot->lastApplyTerm,
                      pSnapshot->lastConfigIndex);
S
Shengliang Guan 已提交
178 179
}

S
Shengliang Guan 已提交
180
int32_t mndSnapshotDoWrite(const SSyncFSM *pFsm, void *pWriter, void *pBuf, int32_t len) {
S
Shengliang Guan 已提交
181 182 183 184
  SMnode *pMnode = pFsm->data;
  return sdbDoWrite(pMnode->pSdb, pWriter, pBuf, len);
}

S
Shengliang Guan 已提交
185
static void mndBecomeFollower(const SSyncFSM *pFsm) {
186
  SMnode *pMnode = pFsm->data;
187
  mInfo("vgId:1, become follower");
188

189
  taosWLockLatch(&pMnode->syncMgmt.lock);
190
  if (pMnode->syncMgmt.transId != 0) {
191 192
    mInfo("vgId:1, become follower and post sem, trans:%d, failed to propose since not leader",
          pMnode->syncMgmt.transId);
193
    pMnode->syncMgmt.transId = 0;
194
    pMnode->syncMgmt.errCode = TSDB_CODE_SYN_NOT_LEADER;
195 196
    tsem_post(&pMnode->syncMgmt.syncSem);
  }
197
  taosWUnLockLatch(&pMnode->syncMgmt.lock);
198 199
}

S
Shengliang Guan 已提交
200
static void mndBecomeLeader(const SSyncFSM *pFsm) {
201
  mInfo("vgId:1, become leader");
202
  SMnode *pMnode = pFsm->data;
203 204
}

205 206
SSyncFSM *mndSyncMakeFsm(SMnode *pMnode) {
  SSyncFSM *pFsm = taosMemoryCalloc(1, sizeof(SSyncFSM));
M
Minghao Li 已提交
207
  pFsm->data = pMnode;
208
  pFsm->FpCommitCb = mndSyncCommitMsg;
209 210
  pFsm->FpPreCommitCb = NULL;
  pFsm->FpRollBackCb = NULL;
211
  pFsm->FpRestoreFinishCb = mndRestoreFinish;
S
Shengliang Guan 已提交
212 213
  pFsm->FpLeaderTransferCb = NULL;
  pFsm->FpReConfigCb = NULL;
214 215
  pFsm->FpBecomeLeaderCb = mndBecomeLeader;
  pFsm->FpBecomeFollowerCb = mndBecomeFollower;
S
Shengliang Guan 已提交
216
  pFsm->FpGetSnapshot = mndSyncGetSnapshot;
217
  pFsm->FpGetSnapshotInfo = mndSyncGetSnapshotInfo;
S
Shengliang Guan 已提交
218 219 220 221 222 223
  pFsm->FpSnapshotStartRead = mndSnapshotStartRead;
  pFsm->FpSnapshotStopRead = mndSnapshotStopRead;
  pFsm->FpSnapshotDoRead = mndSnapshotDoRead;
  pFsm->FpSnapshotStartWrite = mndSnapshotStartWrite;
  pFsm->FpSnapshotStopWrite = mndSnapshotStopWrite;
  pFsm->FpSnapshotDoWrite = mndSnapshotDoWrite;
M
Minghao Li 已提交
224
  return pFsm;
225 226 227 228
}

int32_t mndInitSync(SMnode *pMnode) {
  SSyncMgmt *pMgmt = &pMnode->syncMgmt;
229 230
  taosInitRWLatch(&pMgmt->lock);
  pMgmt->transId = 0;
231

S
Shengliang Guan 已提交
232 233 234 235 236
  SSyncInfo syncInfo = {
      .snapshotStrategy = SYNC_STRATEGY_STANDARD_SNAPSHOT,
      .batchSize = 1,
      .vgId = 1,
      .pWal = pMnode->pWal,
S
Shengliang Guan 已提交
237
      .msgcb = &pMnode->msgCb,
S
Shengliang Guan 已提交
238 239
      .syncSendMSg = mndSyncSendMsg,
      .syncEqMsg = mndSyncEqMsg,
240
      .syncEqCtrlMsg = mndSyncEqCtrlMsg,
S
Shengliang Guan 已提交
241 242 243
      .pingMs = 5000,
      .electMs = 3000,
      .heartbeatMs = 500,
S
Shengliang Guan 已提交
244 245
  };

246 247 248
  snprintf(syncInfo.path, sizeof(syncInfo.path), "%s%ssync", pMnode->path, TD_DIRSEP);
  syncInfo.pFsm = mndSyncMakeFsm(pMnode);

S
Shengliang Guan 已提交
249
  mInfo("vgId:1, start to open sync, replica:%d selfIndex:%d", pMgmt->numOfReplicas, pMgmt->selfIndex);
250 251 252 253 254 255 256 257
  SSyncCfg *pCfg = &syncInfo.syncCfg;
  pCfg->replicaNum = pMgmt->numOfReplicas;
  pCfg->myIndex = pMgmt->selfIndex;
  for (int32_t i = 0; i < pMgmt->numOfReplicas; ++i) {
    SNodeInfo *pNode = &pCfg->nodeInfo[i];
    tstrncpy(pNode->nodeFqdn, pMgmt->replicas[i].fqdn, sizeof(pNode->nodeFqdn));
    pNode->nodePort = pMgmt->replicas[i].port;
    mInfo("vgId:1, index:%d ep:%s:%u", i, pNode->nodeFqdn, pNode->nodePort);
M
Minghao Li 已提交
258 259
  }

260
  tsem_init(&pMgmt->syncSem, 0, 0);
261 262 263 264 265
  pMgmt->sync = syncOpen(&syncInfo);
  if (pMgmt->sync <= 0) {
    mError("failed to open sync since %s", terrstr());
    return -1;
  }
M
Minghao Li 已提交
266

267
  mInfo("mnode-sync is opened, id:%" PRId64, pMgmt->sync);
S
Shengliang Guan 已提交
268 269 270 271 272
  return 0;
}

void mndCleanupSync(SMnode *pMnode) {
  SSyncMgmt *pMgmt = &pMnode->syncMgmt;
273
  syncStop(pMgmt->sync);
274
  mInfo("mnode-sync is stopped, id:%" PRId64, pMgmt->sync);
275

276
  tsem_destroy(&pMgmt->syncSem);
277 278
  memset(pMgmt, 0, sizeof(SSyncMgmt));
}
M
Minghao Li 已提交
279

S
Shengliang Guan 已提交
280
int32_t mndSyncPropose(SMnode *pMnode, SSdbRaw *pRaw, int32_t transId) {
S
Shengliang Guan 已提交
281
  SSyncMgmt *pMgmt = &pMnode->syncMgmt;
S
Shengliang Guan 已提交
282
  pMgmt->errCode = 0;
S
Shengliang Guan 已提交
283

S
Shengliang Guan 已提交
284
  SRpcMsg req = {.msgType = TDMT_MND_APPLY_MSG, .contLen = sdbGetRawTotalSize(pRaw)};
285 286 287
  req.pCont = rpcMallocCont(req.contLen);
  if (req.pCont == NULL) return -1;
  memcpy(req.pCont, pRaw, req.contLen);
S
Shengliang Guan 已提交
288

289
  taosWLockLatch(&pMgmt->lock);
290
  if (pMgmt->transId != 0) {
S
Shengliang Guan 已提交
291
    mError("trans:%d, can't be proposed since trans:%d already waiting for confirm", transId, pMgmt->transId);
292 293 294 295
    taosWUnLockLatch(&pMgmt->lock);
    terrno = TSDB_CODE_APP_NOT_READY;
    return -1;
  }
S
Shengliang Guan 已提交
296

S
Shengliang Guan 已提交
297 298 299
  mInfo("trans:%d, will be proposed", transId);
  pMgmt->transId = transId;
  taosWUnLockLatch(&pMgmt->lock);
300

S
Shengliang Guan 已提交
301
  int32_t code = syncPropose(pMgmt->sync, &req, false);
302
  if (code == 0) {
303
    mInfo("trans:%d, is proposing and wait sem", pMgmt->transId);
304
    tsem_wait(&pMgmt->syncSem);
305 306 307 308 309 310 311 312
  } else if (code > 0) {
    mInfo("trans:%d, confirm at once since replica is 1, continue execute", transId);
    taosWLockLatch(&pMgmt->lock);
    pMgmt->transId = 0;
    taosWUnLockLatch(&pMgmt->lock);
    sdbWriteWithoutFree(pMnode->pSdb, pRaw);
    sdbSetApplyInfo(pMnode->pSdb, req.info.conn.applyIndex, req.info.conn.applyTerm, SYNC_INDEX_INVALID);
    code = 0;
313
  } else {
314
    mInfo("trans:%d, failed to proposed since %s", transId, terrstr());
S
Shengliang Guan 已提交
315
    taosWLockLatch(&pMgmt->lock);
316 317 318 319 320 321 322
    pMgmt->transId = 0;
    taosWUnLockLatch(&pMgmt->lock);
    if (terrno == TSDB_CODE_SYN_NOT_LEADER) {
      terrno = TSDB_CODE_APP_NOT_READY;
    } else {
      terrno = TSDB_CODE_APP_ERROR;
    }
323
  }
324

325
  rpcFreeCont(req.pCont);
S
Shengliang Guan 已提交
326 327 328 329 330
  if (code != 0) {
    mError("trans:%d, failed to propose, code:0x%x", pMgmt->transId, code);
    return code;
  }

S
Shengliang Guan 已提交
331
  terrno = pMgmt->errCode;
S
Shengliang Guan 已提交
332
  return pMgmt->errCode;
333 334
}

335
void mndSyncStart(SMnode *pMnode) {
336
  SSyncMgmt *pMgmt = &pMnode->syncMgmt;
M
Minghao Li 已提交
337
  syncStart(pMgmt->sync);
338
  mInfo("vgId:1, sync started, id:%" PRId64, pMgmt->sync);
339 340
}

S
Shengliang Guan 已提交
341
void mndSyncStop(SMnode *pMnode) {
342
  taosWLockLatch(&pMnode->syncMgmt.lock);
S
Shengliang Guan 已提交
343
  if (pMnode->syncMgmt.transId != 0) {
344
    mInfo("vgId:1, is stopped and post sem, trans:%d", pMnode->syncMgmt.transId);
S
Shengliang Guan 已提交
345
    pMnode->syncMgmt.transId = 0;
S
Shengliang Guan 已提交
346 347
    tsem_post(&pMnode->syncMgmt.syncSem);
  }
348
  taosWUnLockLatch(&pMnode->syncMgmt.lock);
S
Shengliang Guan 已提交
349
}
350

351
bool mndIsLeader(SMnode *pMnode) {
352
  SSyncState state = syncGetState(pMnode->syncMgmt.sync);
353

354 355 356 357 358 359 360
  if (state.state != TAOS_SYNC_STATE_LEADER || !state.restored) {
    if (state.state != TAOS_SYNC_STATE_LEADER) {
      terrno = TSDB_CODE_SYN_NOT_LEADER;
    } else {
      terrno = TSDB_CODE_APP_NOT_READY;
    }
    mDebug("vgId:1, mnode not ready, state:%s, restore:%d", syncStr(state.state), state.restored);
361 362 363
    return false;
  }

364
  if (!mndGetRestored(pMnode)) {
365 366 367 368 369
    terrno = TSDB_CODE_APP_NOT_READY;
    return false;
  }

  return true;
L
Liu Jicong 已提交
370
}