walMeta.c 30.0 KB
Newer Older
L
Liu Jicong 已提交
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/>.
 */

L
Liu Jicong 已提交
16
#include "cJSON.h"
L
Liu Jicong 已提交
17 18
#include "os.h"
#include "taoserror.h"
19
#include "tglobal.h"
L
Liu Jicong 已提交
20
#include "tutil.h"
L
Liu Jicong 已提交
21 22
#include "walInt.h"

23 24 25 26
bool FORCE_INLINE walLogExist(SWal* pWal, int64_t ver) {
  return !walIsEmpty(pWal) && walGetFirstVer(pWal) <= ver && walGetLastVer(pWal) >= ver;
}

27 28 29
bool FORCE_INLINE walIsEmpty(SWal* pWal) {
  return (pWal->vers.firstVer == -1 || pWal->vers.lastVer < pWal->vers.firstVer); // [firstVer, lastVer + 1)
}
L
Liu Jicong 已提交
30

L
Liu Jicong 已提交
31
int64_t FORCE_INLINE walGetFirstVer(SWal* pWal) { return pWal->vers.firstVer; }
L
Liu Jicong 已提交
32

L
Liu Jicong 已提交
33
int64_t FORCE_INLINE walGetSnapshotVer(SWal* pWal) { return pWal->vers.snapshotVer; }
L
Liu Jicong 已提交
34

L
Liu Jicong 已提交
35
int64_t FORCE_INLINE walGetLastVer(SWal* pWal) { return pWal->vers.lastVer; }
L
Liu Jicong 已提交
36

L
Liu Jicong 已提交
37 38
int64_t FORCE_INLINE walGetCommittedVer(SWal* pWal) { return pWal->vers.commitVer; }

L
Liu Jicong 已提交
39 40
int64_t FORCE_INLINE walGetAppliedVer(SWal* pWal) { return pWal->vers.appliedVer; }

41 42 43 44 45 46
static FORCE_INLINE int walBuildMetaName(SWal* pWal, int metaVer, char* buf) {
  return sprintf(buf, "%s/meta-ver%d", pWal->path, metaVer);
}

static FORCE_INLINE int walBuildTmpMetaName(SWal* pWal, char* buf) {
  return sprintf(buf, "%s/meta-ver.tmp", pWal->path);
L
Liu Jicong 已提交
47 48
}

49
static FORCE_INLINE int64_t walScanLogGetLastVer(SWal* pWal, int32_t fileIdx) {
L
Liu Jicong 已提交
50
  int32_t sz = taosArrayGetSize(pWal->fileInfoSet);
51
  terrno = TSDB_CODE_SUCCESS;
52
  ASSERT(fileIdx >= 0 && fileIdx < sz);
L
Liu Jicong 已提交
53

54
  SWalFileInfo* pFileInfo = taosArrayGet(pWal->fileInfoSet, fileIdx);
L
Liu Jicong 已提交
55
  char          fnameStr[WAL_FILE_LEN];
56
  walBuildLogName(pWal, pFileInfo->firstVer, fnameStr);
L
Liu Jicong 已提交
57

L
Liu Jicong 已提交
58 59
  int64_t fileSize = 0;
  taosStatFile(fnameStr, &fileSize, NULL);
L
Liu Jicong 已提交
60

61
  TdFilePtr pFile = taosOpenFile(fnameStr, TD_FILE_READ | TD_FILE_WRITE);
62
  if (pFile == NULL) {
63
    wError("vgId:%d, failed to open file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), fnameStr);
L
Liu Jicong 已提交
64 65 66 67
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }

68 69 70
  // ensure size as non-negative
  pFileInfo->fileSize = TMAX(0, pFileInfo->fileSize);

71
  int64_t  stepSize = WAL_SCAN_BUF_SIZE;
L
Liu Jicong 已提交
72
  uint64_t magic = WAL_MAGIC;
73 74
  int64_t  walCkHeadSz = sizeof(SWalCkHead);
  int64_t  end = fileSize;
75 76
  int64_t  capacity = 0;
  int64_t  readSize = 0;
77 78
  char*    buf = NULL;
  bool     firstTrial = pFileInfo->fileSize < fileSize;
79 80 81
  int64_t  offset = TMIN(pFileInfo->fileSize, fileSize);
  int64_t  offsetForward = offset - stepSize + walCkHeadSz - 1;
  int64_t  offsetBackward = offset;
82 83 84
  int64_t  retVer = -1;
  int64_t  lastEntryBeginOffset = 0;
  int64_t  lastEntryEndOffset = 0;
85

86 87
  // check recover size
  if (2 * tsWalFsyncDataSizeLimit + offset < end) {
88 89 90
    wWarn("vgId:%d, possibly corrupted WAL range exceeds size limit (i.e. %" PRId64 " bytes). offset:%" PRId64
          ", end:%" PRId64 ", file:%s",
          pWal->cfg.vgId, 2 * tsWalFsyncDataSizeLimit, offset, end, fnameStr);
91
  }
92 93 94

  // search for the valid last WAL entry, e.g. block by block
  while (1) {
95 96 97 98 99 100 101 102 103
    offset = (firstTrial) ? TMIN(fileSize, offsetForward + stepSize - walCkHeadSz + 1)
                          : TMAX(0, offsetBackward - stepSize + walCkHeadSz - 1);
    end = TMIN(offset + stepSize, fileSize);
    if (firstTrial) {
      offsetForward = offset;
    } else {
      offsetBackward = offset;
    }

104
    ASSERT(offset <= end);
105 106 107 108 109
    readSize = end - offset;
    capacity = readSize + sizeof(magic);

    void* ptr = taosMemoryRealloc(buf, capacity);
    if (ptr == NULL) {
S
Shengliang Guan 已提交
110
      terrno = TSDB_CODE_OUT_OF_MEMORY;
111 112 113
      goto _err;
    }
    buf = ptr;
L
Liu Jicong 已提交
114

115 116 117 118 119 120 121 122 123 124 125 126 127
    int64_t ret = taosLSeekFile(pFile, offset, SEEK_SET);
    if (ret < 0) {
      wError("vgId:%d, failed to lseek file due to %s. offset:%" PRId64 "", pWal->cfg.vgId, strerror(errno), offset);
      terrno = TAOS_SYSTEM_ERROR(errno);
      goto _err;
    }

    if (readSize != taosReadFile(pFile, buf, readSize)) {
      wError("vgId:%d, failed to read file due to %s. readSize:%" PRId64 ", file:%s", pWal->cfg.vgId, strerror(errno),
             readSize, fnameStr);
      terrno = TAOS_SYSTEM_ERROR(errno);
      goto _err;
    }
L
Liu Jicong 已提交
128

129 130
    char*       candidate = NULL;
    char*       haystack = buf;
131 132
    int64_t     pos = 0;
    SWalCkHead* logContent = NULL;
133 134

    while ((candidate = tmemmem(haystack, readSize - (haystack - buf), (char*)&magic, sizeof(magic))) != NULL) {
135 136
      pos = candidate - buf;

137
      // validate head
138
      int64_t len = readSize - pos;
139
      if (len < walCkHeadSz) {
140
        break;
141
      }
142
      logContent = (SWalCkHead*)(buf + pos);
143
      if (walValidHeadCksum(logContent) != 0) {
144
        terrno = TSDB_CODE_WAL_CHKSUM_MISMATCH;
145
        wWarn("vgId:%d, failed to validate checksum of wal entry header. offset:%" PRId64 ", file:%s", pWal->cfg.vgId,
146 147
              offset + pos, fnameStr);
        haystack = buf + pos + 1;
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
        if (firstTrial) {
          break;
        } else {
          continue;
        }
      }

      // validate body
      int64_t size = walCkHeadSz + logContent->head.bodyLen;
      if (len < size) {
        int64_t extraSize = size - len;
        if (capacity < readSize + extraSize + sizeof(magic)) {
          capacity += extraSize;
          void* ptr = taosMemoryRealloc(buf, capacity);
          if (ptr == NULL) {
            terrno = TSDB_CODE_OUT_OF_MEMORY;
            goto _err;
          }
          buf = ptr;
        }
        int64_t ret = taosLSeekFile(pFile, offset + readSize, SEEK_SET);
        if (ret < 0) {
          wError("vgId:%d, failed to lseek file due to %s. offset:%" PRId64 "", pWal->cfg.vgId, strerror(errno),
                 offset);
          terrno = TAOS_SYSTEM_ERROR(errno);
          break;
        }
        if (extraSize != taosReadFile(pFile, buf + readSize, extraSize)) {
          wError("vgId:%d, failed to read file due to %s. offset:%" PRId64 ", extraSize:%" PRId64 ", file:%s",
                 pWal->cfg.vgId, strerror(errno), offset + readSize, extraSize, fnameStr);
          terrno = TAOS_SYSTEM_ERROR(errno);
          break;
        }
181
      }
182 183

      logContent = (SWalCkHead*)(buf + pos);
184 185
      if (walValidBodyCksum(logContent) != 0) {
        terrno = TSDB_CODE_WAL_CHKSUM_MISMATCH;
186
        wWarn("vgId:%d, failed to validate checksum of wal entry body. offset:%" PRId64 ", file:%s", pWal->cfg.vgId,
187 188
              offset + pos, fnameStr);
        haystack = buf + pos + 1;
189 190 191 192 193 194 195 196
        if (firstTrial) {
          break;
        } else {
          continue;
        }
      }

      // found one
197 198 199 200 201
      retVer = logContent->head.version;
      lastEntryBeginOffset = offset + pos;
      lastEntryEndOffset = offset + pos + sizeof(SWalCkHead) + logContent->head.bodyLen;

      // try next
202
      haystack = buf + pos + 1;
L
Liu Jicong 已提交
203
    }
204

205
    if (end == fileSize) firstTrial = false;
206 207 208 209 210 211 212
    if (firstTrial) {
      if (terrno == TSDB_CODE_SUCCESS) {
        continue;
      } else {
        firstTrial = false;
      }
    }
213
    if (retVer >= 0 || offset == 0) break;
214 215
  }

216
  if (retVer < 0) {
217
    terrno = TSDB_CODE_WAL_LOG_NOT_EXIST;
L
Liu Jicong 已提交
218
  }
L
Liu Jicong 已提交
219 220 221

  // truncate file
  if (lastEntryEndOffset != fileSize) {
222 223
    wWarn("vgId:%d, repair meta truncate file %s to %" PRId64 ", orig size %" PRId64, pWal->cfg.vgId, fnameStr,
          lastEntryEndOffset, fileSize);
224

225
    if (taosFtruncateFile(pFile, lastEntryEndOffset) < 0) {
226 227 228
      wError("failed to truncate file due to %s. file:%s", strerror(errno), fnameStr);
      terrno = TAOS_SYSTEM_ERROR(errno);
      goto _err;
229
    }
230

231
    if (taosFsyncFile(pFile) < 0) {
232 233 234
      wError("failed to fsync file due to %s. file:%s", strerror(errno), fnameStr);
      terrno = TAOS_SYSTEM_ERROR(errno);
      goto _err;
235
    }
L
Liu Jicong 已提交
236
  }
237

238
  pFileInfo->fileSize = lastEntryEndOffset;
L
Liu Jicong 已提交
239

240 241
  taosCloseFile(&pFile);
  taosMemoryFree(buf);
L
Liu Jicong 已提交
242
  return retVer;
243 244 245 246 247

_err:
  taosCloseFile(&pFile);
  taosMemoryFree(buf);
  return -1;
L
Liu Jicong 已提交
248 249
}

250 251 252 253 254 255 256 257 258 259
static void walRebuildFileInfoSet(SArray* metaLogList, SArray* actualLogList) {
  int metaFileNum = taosArrayGetSize(metaLogList);
  int actualFileNum = taosArrayGetSize(actualLogList);
  int j = 0;

  // both of the lists in asc order
  for (int i = 0; i < actualFileNum; i++) {
    SWalFileInfo* pLogInfo = taosArrayGet(actualLogList, i);
    while (j < metaFileNum) {
      SWalFileInfo* pMetaInfo = taosArrayGet(metaLogList, j);
260
      ASSERT(pMetaInfo != NULL);
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
      if (pMetaInfo->firstVer < pLogInfo->firstVer) {
        j++;
      } else if (pMetaInfo->firstVer == pLogInfo->firstVer) {
        (*pLogInfo) = *pMetaInfo;
        j++;
        break;
      } else {
        break;
      }
    }
  }

  taosArrayClear(metaLogList);

  for (int i = 0; i < actualFileNum; i++) {
    SWalFileInfo* pFileInfo = taosArrayGet(actualLogList, i);
    taosArrayPush(metaLogList, pFileInfo);
  }
}

void walAlignVersions(SWal* pWal) {
282 283
  if (pWal->vers.firstVer > pWal->vers.snapshotVer + 1) {
    wWarn("vgId:%d, firstVer:%" PRId64 " is larger than snapshotVer:%" PRId64 " + 1. align with it.", pWal->cfg.vgId,
284
          pWal->vers.firstVer, pWal->vers.snapshotVer);
285
    pWal->vers.firstVer = pWal->vers.snapshotVer + 1;
286 287
  }
  if (pWal->vers.lastVer < pWal->vers.snapshotVer) {
288
    wWarn("vgId:%d, lastVer:%" PRId64 " is less than snapshotVer:%" PRId64 ". align with it.", pWal->cfg.vgId,
289
          pWal->vers.lastVer, pWal->vers.snapshotVer);
290 291 292
    if (pWal->vers.lastVer < pWal->vers.firstVer) {
      pWal->vers.firstVer = pWal->vers.snapshotVer + 1;
    }
293 294 295
    pWal->vers.lastVer = pWal->vers.snapshotVer;
  }
  if (pWal->vers.commitVer < pWal->vers.snapshotVer) {
296
    wWarn("vgId:%d, commitVer:%" PRId64 " is less than snapshotVer:%" PRId64 ". align with it.", pWal->cfg.vgId,
297 298 299 300
          pWal->vers.commitVer, pWal->vers.snapshotVer);
    pWal->vers.commitVer = pWal->vers.snapshotVer;
  }
  if (pWal->vers.appliedVer < pWal->vers.snapshotVer) {
301
    wWarn("vgId:%d, appliedVer:%" PRId64 " is less than snapshotVer:%" PRId64 ". align with it.", pWal->cfg.vgId,
302 303 304 305 306 307 308 309
          pWal->vers.appliedVer, pWal->vers.snapshotVer);
    pWal->vers.appliedVer = pWal->vers.snapshotVer;
  }

  pWal->vers.commitVer = TMIN(pWal->vers.lastVer, pWal->vers.commitVer);
  pWal->vers.appliedVer = TMIN(pWal->vers.commitVer, pWal->vers.appliedVer);
}

310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
bool walLogEntriesComplete(const SWal* pWal) {
  int32_t sz = taosArrayGetSize(pWal->fileInfoSet);
  bool    complete = true;
  int32_t fileIdx = -1;
  int64_t index = pWal->vers.firstVer;

  while (++fileIdx < sz) {
    SWalFileInfo* pFileInfo = taosArrayGet(pWal->fileInfoSet, fileIdx);
    if (pFileInfo->firstVer != index) {
      break;
    }
    index = pFileInfo->lastVer + ((fileIdx + 1 < sz) ? 1 : 0);
  }
  // empty is regarded as complete
  if (sz != 0) {
    complete = (index == pWal->vers.lastVer);
  }

  if (!complete) {
    wError("vgId:%d, WAL log entries incomplete in range [%" PRId64 ", %" PRId64 "], aligned with snaphotVer:%" PRId64,
           pWal->cfg.vgId, pWal->vers.firstVer, pWal->vers.lastVer, pWal->vers.snapshotVer);
    terrno = TSDB_CODE_WAL_LOG_INCOMPLETE;
  }

  return complete;
}

L
Liu Jicong 已提交
337 338 339 340
int walCheckAndRepairMeta(SWal* pWal) {
  // load log files, get first/snapshot/last version info
  const char* logPattern = "^[0-9]+.log$";
  const char* idxPattern = "^[0-9]+.idx$";
L
Liu Jicong 已提交
341 342
  regex_t     logRegPattern;
  regex_t     idxRegPattern;
L
Liu Jicong 已提交
343 344 345

  regcomp(&logRegPattern, logPattern, REG_EXTENDED);
  regcomp(&idxRegPattern, idxPattern, REG_EXTENDED);
L
Liu Jicong 已提交
346

wafwerar's avatar
wafwerar 已提交
347 348
  TdDirPtr pDir = taosOpenDir(pWal->path);
  if (pDir == NULL) {
L
Liu Jicong 已提交
349 350
    regfree(&logRegPattern);
    regfree(&idxRegPattern);
L
Liu Jicong 已提交
351 352 353 354
    wError("vgId:%d, path:%s, failed to open since %s", pWal->cfg.vgId, pWal->path, strerror(errno));
    return -1;
  }

355 356
  SArray* actualLog = taosArrayInit(8, sizeof(SWalFileInfo));

L
Liu Jicong 已提交
357
  // scan log files and build new meta
wafwerar's avatar
wafwerar 已提交
358 359 360
  TdDirEntryPtr pDirEntry;
  while ((pDirEntry = taosReadDir(pDir)) != NULL) {
    char* name = taosDirEntryBaseName(taosGetDirEntryName(pDirEntry));
L
Liu Jicong 已提交
361 362
    int   code = regexec(&logRegPattern, name, 0, NULL, 0);
    if (code == 0) {
L
Liu Jicong 已提交
363 364 365
      SWalFileInfo fileInfo;
      memset(&fileInfo, -1, sizeof(SWalFileInfo));
      sscanf(name, "%" PRId64 ".log", &fileInfo.firstVer);
366
      taosArrayPush(actualLog, &fileInfo);
L
Liu Jicong 已提交
367 368 369
    }
  }

wafwerar's avatar
wafwerar 已提交
370
  taosCloseDir(&pDir);
L
Liu Jicong 已提交
371 372 373
  regfree(&logRegPattern);
  regfree(&idxRegPattern);

374
  taosArraySort(actualLog, compareWalFileInfo);
L
Liu Jicong 已提交
375

376 377 378 379 380 381 382 383 384 385 386 387
  int     metaFileNum = taosArrayGetSize(pWal->fileInfoSet);
  int     actualFileNum = taosArrayGetSize(actualLog);
  int64_t firstVerPrev = pWal->vers.firstVer;
  int64_t lastVerPrev = pWal->vers.lastVer;
  int64_t totSize = 0;
  bool    updateMeta = (metaFileNum != actualFileNum);

  // rebuild meta of file info
  walRebuildFileInfoSet(pWal->fileInfoSet, actualLog);
  taosArrayDestroy(actualLog);

  int32_t sz = taosArrayGetSize(pWal->fileInfoSet);
388
  ASSERT(sz == actualFileNum);
L
Liu Jicong 已提交
389

390 391 392 393
  // scan and determine the lastVer
  int32_t fileIdx = sz;

  while (--fileIdx >= 0) {
L
Liu Jicong 已提交
394
    char          fnameStr[WAL_FILE_LEN];
395 396 397
    int64_t       fileSize = 0;
    SWalFileInfo* pFileInfo = taosArrayGet(pWal->fileInfoSet, fileIdx);

L
Liu Jicong 已提交
398
    walBuildLogName(pWal, pFileInfo->firstVer, fnameStr);
399 400 401 402 403
    int32_t code = taosStatFile(fnameStr, &fileSize, NULL);
    if (code < 0) {
      terrno = TAOS_SYSTEM_ERROR(errno);
      wError("failed to stat file since %s. file:%s", terrstr(), fnameStr);
      return -1;
L
Liu Jicong 已提交
404 405
    }

406
    ASSERT(pFileInfo->firstVer >= 0);
407 408 409 410

    if (pFileInfo->lastVer >= pFileInfo->firstVer && fileSize == pFileInfo->fileSize) {
      totSize += pFileInfo->fileSize;
      continue;
L
Liu Jicong 已提交
411
    }
412
    updateMeta = true;
L
Liu Jicong 已提交
413

414 415 416 417 418
    int64_t lastVer = walScanLogGetLastVer(pWal, fileIdx);
    if (lastVer < 0) {
      if (terrno != TSDB_CODE_WAL_LOG_NOT_EXIST) {
        wError("failed to scan wal last ver since %s", terrstr());
        return -1;
L
Liu Jicong 已提交
419
      }
420
      ASSERT(pFileInfo->fileSize == 0);
421
      // remove the empty wal log, and its idx
422
      wInfo("vgId:%d, wal remove empty file %s", pWal->cfg.vgId, fnameStr);
423 424
      taosRemoveFile(fnameStr);
      walBuildIdxName(pWal, pFileInfo->firstVer, fnameStr);
425
      wInfo("vgId:%d, wal remove empty file %s", pWal->cfg.vgId, fnameStr);
426 427 428 429
      taosRemoveFile(fnameStr);
      // remove its meta entry
      taosArrayRemove(pWal->fileInfoSet, fileIdx);
      continue;
L
Liu Jicong 已提交
430 431
    }

432 433 434
    // update lastVer
    pFileInfo->lastVer = lastVer;
    totSize += pFileInfo->fileSize;
L
Liu Jicong 已提交
435
  }
L
Liu Jicong 已提交
436

437
  // reset vers info and so on
L
Liu Jicong 已提交
438
  actualFileNum = taosArrayGetSize(pWal->fileInfoSet);
L
Liu Jicong 已提交
439
  pWal->writeCur = actualFileNum - 1;
440 441
  pWal->totSize = totSize;
  pWal->vers.lastVer = -1;
L
Liu Jicong 已提交
442
  if (actualFileNum > 0) {
443 444
    pWal->vers.firstVer = ((SWalFileInfo*)taosArrayGet(pWal->fileInfoSet, 0))->firstVer;
    pWal->vers.lastVer = ((SWalFileInfo*)taosArrayGetLast(pWal->fileInfoSet))->lastVer;
L
Liu Jicong 已提交
445
  }
446
  (void)walAlignVersions(pWal);
L
Liu Jicong 已提交
447

448 449 450 451
  // update meta file
  if (updateMeta) {
    (void)walSaveMeta(pWal);
  }
452 453 454 455 456

  if (!walLogEntriesComplete(pWal)) {
    return -1;
  }

457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
  return 0;
}

int walReadLogHead(TdFilePtr pLogFile, int64_t offset, SWalCkHead* pCkHead) {
  if (taosLSeekFile(pLogFile, offset, SEEK_SET) < 0) {
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }

  if (taosReadFile(pLogFile, pCkHead, sizeof(SWalCkHead)) != sizeof(SWalCkHead)) {
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }

  if (walValidHeadCksum(pCkHead) != 0) {
    terrno = TSDB_CODE_WAL_CHKSUM_MISMATCH;
    return -1;
L
Liu Jicong 已提交
474 475
  }

L
Liu Jicong 已提交
476 477 478
  return 0;
}

479
int walCheckAndRepairIdxFile(SWal* pWal, int32_t fileIdx) {
L
Liu Jicong 已提交
480
  int32_t sz = taosArrayGetSize(pWal->fileInfoSet);
481
  ASSERT(fileIdx >= 0 && fileIdx < sz);
482 483 484 485 486 487 488 489 490 491 492 493 494
  SWalFileInfo* pFileInfo = taosArrayGet(pWal->fileInfoSet, fileIdx);
  char          fnameStr[WAL_FILE_LEN];
  walBuildIdxName(pWal, pFileInfo->firstVer, fnameStr);
  char fLogNameStr[WAL_FILE_LEN];
  walBuildLogName(pWal, pFileInfo->firstVer, fLogNameStr);
  int64_t fileSize = 0;

  if (taosStatFile(fnameStr, &fileSize, NULL) < 0 && errno != ENOENT) {
    wError("vgId:%d, failed to stat file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), fnameStr);
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }

495
  ASSERT(pFileInfo->fileSize > 0 && pFileInfo->firstVer >= 0 && pFileInfo->lastVer >= pFileInfo->firstVer);
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
  if (fileSize == (pFileInfo->lastVer - pFileInfo->firstVer + 1) * sizeof(SWalIdxEntry)) {
    return 0;
  }

  // start to repair
  int64_t      offset = fileSize - fileSize % sizeof(SWalIdxEntry);
  TdFilePtr    pLogFile = NULL;
  TdFilePtr    pIdxFile = NULL;
  SWalIdxEntry idxEntry = {.ver = pFileInfo->firstVer - 1, .offset = -sizeof(SWalCkHead)};
  SWalCkHead   ckHead;
  memset(&ckHead, 0, sizeof(ckHead));
  ckHead.head.version = idxEntry.ver;

  pIdxFile = taosOpenFile(fnameStr, TD_FILE_READ | TD_FILE_WRITE | TD_FILE_CREATE);
  if (pIdxFile == NULL) {
    wError("vgId:%d, failed to open file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), fnameStr);
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

  pLogFile = taosOpenFile(fLogNameStr, TD_FILE_READ);
  if (pLogFile == NULL) {
    terrno = TAOS_SYSTEM_ERROR(errno);
    wError("vgId:%d, cannot open file %s, since %s", pWal->cfg.vgId, fLogNameStr, terrstr());
    goto _err;
  }

  // determine the last valid entry end, i.e. offset
  while ((offset -= sizeof(SWalIdxEntry)) >= 0) {
    if (taosLSeekFile(pIdxFile, offset, SEEK_SET) < 0) {
526
      wError("vgId:%d, failed to seek file due to %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId, strerror(errno),
527
             offset, fnameStr);
L
Liu Jicong 已提交
528
      terrno = TAOS_SYSTEM_ERROR(errno);
529 530 531 532 533 534 535 536
      goto _err;
    }

    if (taosReadFile(pIdxFile, &idxEntry, sizeof(SWalIdxEntry)) != sizeof(SWalIdxEntry)) {
      wError("vgId:%d, failed to read file due to %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId, strerror(errno),
             offset, fnameStr);
      terrno = TAOS_SYSTEM_ERROR(errno);
      goto _err;
L
Liu Jicong 已提交
537 538
    }

539
    if (idxEntry.ver > pFileInfo->lastVer) {
L
Liu Jicong 已提交
540 541
      continue;
    }
L
Liu Jicong 已提交
542

543 544 545 546
    if (offset != (idxEntry.ver - pFileInfo->firstVer) * sizeof(SWalIdxEntry)) {
      continue;
    }

547 548 549 550
    if (walReadLogHead(pLogFile, idxEntry.offset, &ckHead) < 0) {
      wWarn("vgId:%d, failed to read log file since %s. file:%s, offset:%" PRId64 ", idx entry ver:%" PRId64 "",
            pWal->cfg.vgId, terrstr(), fLogNameStr, idxEntry.offset, idxEntry.ver);
      continue;
L
Liu Jicong 已提交
551 552
    }

553 554
    if (idxEntry.ver == ckHead.head.version) {
      break;
L
Liu Jicong 已提交
555
    }
556 557
  }
  offset += sizeof(SWalIdxEntry);
L
Liu Jicong 已提交
558

559
  ASSERT(offset == (idxEntry.ver - pFileInfo->firstVer + 1) * sizeof(SWalIdxEntry));
560

561 562 563 564 565 566 567 568 569 570 571 572
  // ftruncate idx file
  if (offset < fileSize) {
    if (taosFtruncateFile(pIdxFile, offset) < 0) {
      wError("vgId:%d, failed to ftruncate file due to %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId,
             strerror(errno), offset, fnameStr);
      terrno = TAOS_SYSTEM_ERROR(errno);
      goto _err;
    }
  }

  // rebuild idx file
  if (taosLSeekFile(pIdxFile, 0, SEEK_END) < 0) {
573
    wError("vgId:%d, failed to seek file due to %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId, strerror(errno),
574 575 576 577 578 579
           offset, fnameStr);
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

  while (idxEntry.ver < pFileInfo->lastVer) {
580
    ASSERT(idxEntry.ver == ckHead.head.version);
581 582 583 584 585 586 587 588 589

    idxEntry.ver += 1;
    idxEntry.offset += sizeof(SWalCkHead) + ckHead.head.bodyLen;

    if (walReadLogHead(pLogFile, idxEntry.offset, &ckHead) < 0) {
      wError("vgId:%d, failed to read wal log head since %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId, terrstr(),
             idxEntry.offset, fLogNameStr);
      goto _err;
    }
S
Shengliang Guan 已提交
590
    wWarn("vgId:%d, wal idx append new entry %" PRId64 " %" PRId64, pWal->cfg.vgId, idxEntry.ver, idxEntry.offset);
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
    if (taosWriteFile(pIdxFile, &idxEntry, sizeof(SWalIdxEntry)) < 0) {
      wError("vgId:%d, failed to append file since %s. file:%s", pWal->cfg.vgId, terrstr(), fnameStr);
      goto _err;
    }
  }

  if (taosFsyncFile(pIdxFile) < 0) {
    wError("vgId:%d, faild to fsync file since %s. file:%s", pWal->cfg.vgId, terrstr(), fnameStr);
    goto _err;
  }

  (void)taosCloseFile(&pLogFile);
  (void)taosCloseFile(&pIdxFile);
  return 0;

_err:
  (void)taosCloseFile(&pLogFile);
  (void)taosCloseFile(&pIdxFile);
  return -1;
}

int walCheckAndRepairIdx(SWal* pWal) {
  int32_t sz = taosArrayGetSize(pWal->fileInfoSet);
  int32_t fileIdx = sz;
  while (--fileIdx >= 0) {
    if (walCheckAndRepairIdxFile(pWal, fileIdx) < 0) {
      wError("vgId:%d, failed to repair idx file since %s. fileIdx:%d", pWal->cfg.vgId, terrstr(), fileIdx);
      return -1;
L
Liu Jicong 已提交
619 620
    }
  }
L
Liu Jicong 已提交
621 622 623
  return 0;
}

L
Liu Jicong 已提交
624 625 626 627
int walRollFileInfo(SWal* pWal) {
  int64_t ts = taosGetTimestampSec();

  SArray* pArray = pWal->fileInfoSet;
L
Liu Jicong 已提交
628
  if (taosArrayGetSize(pArray) != 0) {
L
Liu Jicong 已提交
629
    SWalFileInfo* pInfo = taosArrayGetLast(pArray);
L
Liu Jicong 已提交
630
    pInfo->lastVer = pWal->vers.lastVer;
L
Liu Jicong 已提交
631 632 633
    pInfo->closeTs = ts;
  }

L
Liu Jicong 已提交
634
  // TODO: change to emplace back
wafwerar's avatar
wafwerar 已提交
635
  SWalFileInfo* pNewInfo = taosMemoryMalloc(sizeof(SWalFileInfo));
L
Liu Jicong 已提交
636
  if (pNewInfo == NULL) {
S
Shengliang Guan 已提交
637
    terrno = TSDB_CODE_OUT_OF_MEMORY;
L
Liu Jicong 已提交
638 639
    return -1;
  }
L
Liu Jicong 已提交
640
  pNewInfo->firstVer = pWal->vers.lastVer + 1;
L
Liu Jicong 已提交
641 642 643 644
  pNewInfo->lastVer = -1;
  pNewInfo->createTs = ts;
  pNewInfo->closeTs = -1;
  pNewInfo->fileSize = 0;
645
  pNewInfo->syncedOffset = 0;
L
Liu Jicong 已提交
646
  taosArrayPush(pArray, pNewInfo);
wafwerar's avatar
wafwerar 已提交
647
  taosMemoryFree(pNewInfo);
L
Liu Jicong 已提交
648 649 650
  return 0;
}

651
char* walMetaSerialize(SWal* pWal) {
L
Liu Jicong 已提交
652
  char buf[30];
653
  ASSERT(pWal->fileInfoSet);
L
Liu Jicong 已提交
654
  int    sz = taosArrayGetSize(pWal->fileInfoSet);
655 656 657 658
  cJSON* pRoot = cJSON_CreateObject();
  cJSON* pMeta = cJSON_CreateObject();
  cJSON* pFiles = cJSON_CreateArray();
  cJSON* pField;
L
Liu Jicong 已提交
659
  if (pRoot == NULL || pMeta == NULL || pFiles == NULL) {
L
Liu Jicong 已提交
660
    if (pRoot) {
L
Liu Jicong 已提交
661 662
      cJSON_Delete(pRoot);
    }
L
Liu Jicong 已提交
663
    if (pMeta) {
L
Liu Jicong 已提交
664 665
      cJSON_Delete(pMeta);
    }
L
Liu Jicong 已提交
666
    if (pFiles) {
L
Liu Jicong 已提交
667 668
      cJSON_Delete(pFiles);
    }
S
Shengliang Guan 已提交
669
    terrno = TSDB_CODE_OUT_OF_MEMORY;
L
Liu Jicong 已提交
670 671
    return NULL;
  }
672
  cJSON_AddItemToObject(pRoot, "meta", pMeta);
L
Liu Jicong 已提交
673
  sprintf(buf, "%" PRId64, pWal->vers.firstVer);
674
  cJSON_AddStringToObject(pMeta, "firstVer", buf);
L
Liu Jicong 已提交
675
  sprintf(buf, "%" PRId64, pWal->vers.snapshotVer);
676
  cJSON_AddStringToObject(pMeta, "snapshotVer", buf);
L
Liu Jicong 已提交
677
  sprintf(buf, "%" PRId64, pWal->vers.commitVer);
678
  cJSON_AddStringToObject(pMeta, "commitVer", buf);
L
Liu Jicong 已提交
679
  sprintf(buf, "%" PRId64, pWal->vers.lastVer);
680 681 682
  cJSON_AddStringToObject(pMeta, "lastVer", buf);

  cJSON_AddItemToObject(pRoot, "files", pFiles);
L
Liu Jicong 已提交
683
  SWalFileInfo* pData = pWal->fileInfoSet->pData;
L
Liu Jicong 已提交
684
  for (int i = 0; i < sz; i++) {
L
Liu Jicong 已提交
685
    SWalFileInfo* pInfo = &pData[i];
686
    cJSON_AddItemToArray(pFiles, pField = cJSON_CreateObject());
L
Liu Jicong 已提交
687
    if (pField == NULL) {
688
      cJSON_Delete(pRoot);
L
Liu Jicong 已提交
689 690
      return NULL;
    }
L
Liu Jicong 已提交
691 692
    // cjson only support int32_t or double
    // string are used to prohibit the loss of precision
693 694 695 696 697 698 699 700 701 702
    sprintf(buf, "%" PRId64, pInfo->firstVer);
    cJSON_AddStringToObject(pField, "firstVer", buf);
    sprintf(buf, "%" PRId64, pInfo->lastVer);
    cJSON_AddStringToObject(pField, "lastVer", buf);
    sprintf(buf, "%" PRId64, pInfo->createTs);
    cJSON_AddStringToObject(pField, "createTs", buf);
    sprintf(buf, "%" PRId64, pInfo->closeTs);
    cJSON_AddStringToObject(pField, "closeTs", buf);
    sprintf(buf, "%" PRId64, pInfo->fileSize);
    cJSON_AddStringToObject(pField, "fileSize", buf);
L
Liu Jicong 已提交
703
  }
L
Liu Jicong 已提交
704 705 706
  char* serialized = cJSON_Print(pRoot);
  cJSON_Delete(pRoot);
  return serialized;
L
Liu Jicong 已提交
707 708
}

709
int walMetaDeserialize(SWal* pWal, const char* bytes) {
710
  ASSERT(taosArrayGetSize(pWal->fileInfoSet) == 0);
711 712
  cJSON *pRoot, *pMeta, *pFiles, *pInfoJson, *pField;
  pRoot = cJSON_Parse(bytes);
713
  if (!pRoot) goto _err;
714
  pMeta = cJSON_GetObjectItem(pRoot, "meta");
715
  if (!pMeta) goto _err;
716
  pField = cJSON_GetObjectItem(pMeta, "firstVer");
717
  if (!pField) goto _err;
L
Liu Jicong 已提交
718
  pWal->vers.firstVer = atoll(cJSON_GetStringValue(pField));
719
  pField = cJSON_GetObjectItem(pMeta, "snapshotVer");
720
  if (!pField) goto _err;
L
Liu Jicong 已提交
721
  pWal->vers.snapshotVer = atoll(cJSON_GetStringValue(pField));
722
  pField = cJSON_GetObjectItem(pMeta, "commitVer");
723
  if (!pField) goto _err;
L
Liu Jicong 已提交
724
  pWal->vers.commitVer = atoll(cJSON_GetStringValue(pField));
725
  pField = cJSON_GetObjectItem(pMeta, "lastVer");
726
  if (!pField) goto _err;
L
Liu Jicong 已提交
727
  pWal->vers.lastVer = atoll(cJSON_GetStringValue(pField));
728 729 730

  pFiles = cJSON_GetObjectItem(pRoot, "files");
  int sz = cJSON_GetArraySize(pFiles);
L
Liu Jicong 已提交
731
  // deserialize
L
Liu Jicong 已提交
732 733
  SArray* pArray = pWal->fileInfoSet;
  taosArrayEnsureCap(pArray, sz);
L
Liu Jicong 已提交
734
  SWalFileInfo* pData = pArray->pData;
L
Liu Jicong 已提交
735
  for (int i = 0; i < sz; i++) {
736
    cJSON* pInfoJson = cJSON_GetArrayItem(pFiles, i);
737
    if (!pInfoJson) goto _err;
L
Liu Jicong 已提交
738
    SWalFileInfo* pInfo = &pData[i];
L
Liu Jicong 已提交
739
    pField = cJSON_GetObjectItem(pInfoJson, "firstVer");
740
    if (!pField) goto _err;
L
Liu Jicong 已提交
741 742
    pInfo->firstVer = atoll(cJSON_GetStringValue(pField));
    pField = cJSON_GetObjectItem(pInfoJson, "lastVer");
743
    if (!pField) goto _err;
L
Liu Jicong 已提交
744 745
    pInfo->lastVer = atoll(cJSON_GetStringValue(pField));
    pField = cJSON_GetObjectItem(pInfoJson, "createTs");
746
    if (!pField) goto _err;
L
Liu Jicong 已提交
747 748
    pInfo->createTs = atoll(cJSON_GetStringValue(pField));
    pField = cJSON_GetObjectItem(pInfoJson, "closeTs");
749
    if (!pField) goto _err;
L
Liu Jicong 已提交
750 751
    pInfo->closeTs = atoll(cJSON_GetStringValue(pField));
    pField = cJSON_GetObjectItem(pInfoJson, "fileSize");
752
    if (!pField) goto _err;
L
Liu Jicong 已提交
753 754 755
    pInfo->fileSize = atoll(cJSON_GetStringValue(pField));
  }
  taosArraySetSize(pArray, sz);
756
  pWal->fileInfoSet = pArray;
L
Liu Jicong 已提交
757
  pWal->writeCur = sz - 1;
L
Liu Jicong 已提交
758
  cJSON_Delete(pRoot);
759
  return 0;
760 761 762 763

_err:
  cJSON_Delete(pRoot);
  return -1;
L
Liu Jicong 已提交
764 765 766
}

static int walFindCurMetaVer(SWal* pWal) {
L
Liu Jicong 已提交
767 768
  const char* pattern = "^meta-ver[0-9]+$";
  regex_t     walMetaRegexPattern;
L
Liu Jicong 已提交
769 770
  regcomp(&walMetaRegexPattern, pattern, REG_EXTENDED);

wafwerar's avatar
wafwerar 已提交
771 772
  TdDirPtr pDir = taosOpenDir(pWal->path);
  if (pDir == NULL) {
L
Liu Jicong 已提交
773
    wError("vgId:%d, path:%s, failed to open since %s", pWal->cfg.vgId, pWal->path, strerror(errno));
L
Liu Jicong 已提交
774 775 776
    return -1;
  }

wafwerar's avatar
wafwerar 已提交
777
  TdDirEntryPtr pDirEntry;
L
Liu Jicong 已提交
778

L
Liu Jicong 已提交
779
  // find existing meta-ver[x].json
L
Liu Jicong 已提交
780
  int metaVer = -1;
wafwerar's avatar
wafwerar 已提交
781 782
  while ((pDirEntry = taosReadDir(pDir)) != NULL) {
    char* name = taosDirEntryBaseName(taosGetDirEntryName(pDirEntry));
L
Liu Jicong 已提交
783 784
    int   code = regexec(&walMetaRegexPattern, name, 0, NULL, 0);
    if (code == 0) {
L
Liu Jicong 已提交
785
      sscanf(name, "meta-ver%d", &metaVer);
L
Liu Jicong 已提交
786
      wDebug("vgId:%d, wal find current meta: %s is the meta file, ver %d", pWal->cfg.vgId, name, metaVer);
L
Liu Jicong 已提交
787 788
      break;
    }
L
Liu Jicong 已提交
789
    wDebug("vgId:%d, wal find current meta: %s is not meta file", pWal->cfg.vgId, name);
L
Liu Jicong 已提交
790
  }
wafwerar's avatar
wafwerar 已提交
791
  taosCloseDir(&pDir);
L
Liu Jicong 已提交
792
  regfree(&walMetaRegexPattern);
L
Liu Jicong 已提交
793 794 795
  return metaVer;
}

796 797 798 799 800 801
void walUpdateSyncedOffset(SWal* pWal) {
  SWalFileInfo* pFileInfo = walGetCurFileInfo(pWal);
  if (pFileInfo == NULL) return;
  pFileInfo->syncedOffset = pFileInfo->fileSize;
}

L
Liu Jicong 已提交
802
int walSaveMeta(SWal* pWal) {
L
Liu Jicong 已提交
803
  int  metaVer = walFindCurMetaVer(pWal);
L
Liu Jicong 已提交
804
  char fnameStr[WAL_FILE_LEN];
805
  char tmpFnameStr[WAL_FILE_LEN];
806 807 808 809 810 811 812 813 814 815 816 817 818 819
  int  n;

  // fsync the idx and log file at first to ensure validity of meta
  if (taosFsyncFile(pWal->pIdxFile) < 0) {
    wError("vgId:%d, failed to sync idx file due to %s", pWal->cfg.vgId, strerror(errno));
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }

  if (taosFsyncFile(pWal->pLogFile) < 0) {
    wError("vgId:%d, failed to sync log file due to %s", pWal->cfg.vgId, strerror(errno));
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }
820

821 822 823
  // update synced offset
  (void)walUpdateSyncedOffset(pWal);

824 825
  // flush to a tmpfile
  n = walBuildTmpMetaName(pWal, tmpFnameStr);
826
  ASSERT(n < sizeof(tmpFnameStr) && "Buffer overflow of file name");
827 828

  TdFilePtr pMetaFile = taosOpenFile(tmpFnameStr, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
L
Liu Jicong 已提交
829
  if (pMetaFile == NULL) {
830
    wError("vgId:%d, failed to open file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
831
    terrno = TAOS_SYSTEM_ERROR(errno);
L
Liu Jicong 已提交
832 833
    return -1;
  }
834

835
  char* serialized = walMetaSerialize(pWal);
L
Liu Jicong 已提交
836
  int   len = strlen(serialized);
L
Liu Jicong 已提交
837
  if (len != taosWriteFile(pMetaFile, serialized, len)) {
838
    wError("vgId:%d, failed to write file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
839 840 841
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }
L
Liu Jicong 已提交
842

843
  if (taosFsyncFile(pMetaFile) < 0) {
844
    wError("vgId:%d, failed to sync file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
845 846 847 848 849
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

  if (taosCloseFile(&pMetaFile) < 0) {
850
    wError("vgId:%d, failed to close file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
851 852 853 854 855 856
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

  // rename it
  n = walBuildMetaName(pWal, metaVer + 1, fnameStr);
857
  ASSERT(n < sizeof(fnameStr) && "Buffer overflow of file name");
858 859 860 861 862

  if (taosRenameFile(tmpFnameStr, fnameStr) < 0) {
    wError("failed to rename file due to %s. dest:%s", strerror(errno), fnameStr);
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
L
Liu Jicong 已提交
863
  }
L
Liu Jicong 已提交
864 865 866

  // delete old file
  if (metaVer > -1) {
L
Liu Jicong 已提交
867
    walBuildMetaName(pWal, metaVer, fnameStr);
868
    taosRemoveFile(fnameStr);
L
Liu Jicong 已提交
869
  }
wafwerar's avatar
wafwerar 已提交
870
  taosMemoryFree(serialized);
L
Liu Jicong 已提交
871
  return 0;
872 873 874 875 876

_err:
  taosCloseFile(&pMetaFile);
  taosMemoryFree(serialized);
  return -1;
L
Liu Jicong 已提交
877 878
}

L
Liu Jicong 已提交
879
int walLoadMeta(SWal* pWal) {
880
  ASSERT(pWal->fileInfoSet->size == 0);
L
Liu Jicong 已提交
881
  // find existing meta file
L
Liu Jicong 已提交
882
  int metaVer = walFindCurMetaVer(pWal);
L
Liu Jicong 已提交
883
  if (metaVer == -1) {
S
Shengliang Guan 已提交
884
    wDebug("vgId:%d, wal find meta ver %d", pWal->cfg.vgId, metaVer);
L
Liu Jicong 已提交
885
    return -1;
L
Liu Jicong 已提交
886 887 888
  }
  char fnameStr[WAL_FILE_LEN];
  walBuildMetaName(pWal, metaVer, fnameStr);
L
Liu Jicong 已提交
889
  // read metafile
L
Liu Jicong 已提交
890 891
  int64_t fileSize = 0;
  taosStatFile(fnameStr, &fileSize, NULL);
L
Liu Jicong 已提交
892 893
  if (fileSize == 0) {
    taosRemoveFile(fnameStr);
S
Shengliang Guan 已提交
894
    wDebug("vgId:%d, wal find empty meta ver %d", pWal->cfg.vgId, metaVer);
L
Liu Jicong 已提交
895 896
    return -1;
  }
L
Liu Jicong 已提交
897
  int   size = (int)fileSize;
wafwerar's avatar
wafwerar 已提交
898
  char* buf = taosMemoryMalloc(size + 5);
L
Liu Jicong 已提交
899
  if (buf == NULL) {
S
Shengliang Guan 已提交
900
    terrno = TSDB_CODE_OUT_OF_MEMORY;
L
Liu Jicong 已提交
901 902
    return -1;
  }
L
Liu Jicong 已提交
903
  memset(buf, 0, size + 5);
904 905
  TdFilePtr pFile = taosOpenFile(fnameStr, TD_FILE_READ);
  if (pFile == NULL) {
L
Liu Jicong 已提交
906
    terrno = TSDB_CODE_WAL_FILE_CORRUPTED;
L
Liu Jicong 已提交
907
    taosMemoryFree(buf);
L
Liu Jicong 已提交
908 909
    return -1;
  }
910
  if (taosReadFile(pFile, buf, size) != size) {
L
Liu Jicong 已提交
911
    terrno = TAOS_SYSTEM_ERROR(errno);
912
    taosCloseFile(&pFile);
wafwerar's avatar
wafwerar 已提交
913
    taosMemoryFree(buf);
L
Liu Jicong 已提交
914 915
    return -1;
  }
L
Liu Jicong 已提交
916
  // load into fileInfoSet
917
  int code = walMetaDeserialize(pWal, buf);
918 919 920 921
  if (code < 0) {
    wError("failed to deserialize wal meta. file:%s", fnameStr);
    terrno = TSDB_CODE_WAL_FILE_CORRUPTED;
  }
922
  taosCloseFile(&pFile);
wafwerar's avatar
wafwerar 已提交
923
  taosMemoryFree(buf);
L
Liu Jicong 已提交
924
  return code;
L
Liu Jicong 已提交
925
}
926 927 928 929 930 931

int walRemoveMeta(SWal* pWal) {
  int metaVer = walFindCurMetaVer(pWal);
  if (metaVer == -1) return 0;
  char fnameStr[WAL_FILE_LEN];
  walBuildMetaName(pWal, metaVer, fnameStr);
L
Liu Jicong 已提交
932
  return taosRemoveFile(fnameStr);
933
}