walMeta.c 29.8 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;
}

L
Liu Jicong 已提交
27 28
bool FORCE_INLINE walIsEmpty(SWal* pWal) { return pWal->vers.firstVer == -1; }

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

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

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

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

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

39 40 41 42 43 44
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 已提交
45 46
}

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

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

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

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

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

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

84 85
  // check recover size
  if (2 * tsWalFsyncDataSizeLimit + offset < end) {
86 87 88
    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);
89
  }
90 91 92

  // search for the valid last WAL entry, e.g. block by block
  while (1) {
93 94 95 96 97 98 99 100 101
    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;
    }

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

    void* ptr = taosMemoryRealloc(buf, capacity);
    if (ptr == NULL) {
      terrno = TSDB_CODE_WAL_OUT_OF_MEMORY;
      goto _err;
    }
    buf = ptr;
L
Liu Jicong 已提交
112

113 114 115 116 117 118 119 120 121 122 123 124 125
    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 已提交
126

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

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

135
      // validate head
136
      int64_t len = readSize - pos;
137
      if (len < walCkHeadSz) {
138
        break;
139
      }
140
      logContent = (SWalCkHead*)(buf + pos);
141
      if (walValidHeadCksum(logContent) != 0) {
142
        terrno = TSDB_CODE_WAL_CHKSUM_MISMATCH;
143
        wWarn("vgId:%d, failed to validate checksum of wal entry header. offset:%" PRId64 ", file:%s", pWal->cfg.vgId,
144 145
              offset + pos, fnameStr);
        haystack = buf + pos + 1;
146 147 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
        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;
        }
179
      }
180 181

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

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

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

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

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

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

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

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

236
  pFileInfo->fileSize = lastEntryEndOffset;
L
Liu Jicong 已提交
237

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

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

248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
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);
      ASSERT(pMetaInfo != NULL);
      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) {
280 281
  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,
282
          pWal->vers.firstVer, pWal->vers.snapshotVer);
283
    pWal->vers.firstVer = pWal->vers.snapshotVer + 1;
284 285
  }
  if (pWal->vers.lastVer < pWal->vers.snapshotVer) {
286
    wWarn("vgId:%d, lastVer:%" PRId64 " is less than snapshotVer:%" PRId64 ". align with it.", pWal->cfg.vgId,
287 288 289 290
          pWal->vers.lastVer, pWal->vers.snapshotVer);
    pWal->vers.lastVer = pWal->vers.snapshotVer;
  }
  if (pWal->vers.commitVer < pWal->vers.snapshotVer) {
291
    wWarn("vgId:%d, commitVer:%" PRId64 " is less than snapshotVer:%" PRId64 ". align with it.", pWal->cfg.vgId,
292 293 294 295
          pWal->vers.commitVer, pWal->vers.snapshotVer);
    pWal->vers.commitVer = pWal->vers.snapshotVer;
  }
  if (pWal->vers.appliedVer < pWal->vers.snapshotVer) {
296
    wWarn("vgId:%d, appliedVer:%" PRId64 " is less than snapshotVer:%" PRId64 ". align with it.", pWal->cfg.vgId,
297 298 299 300 301 302 303 304
          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);
}

305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
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 已提交
332 333 334 335
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 已提交
336 337
  regex_t     logRegPattern;
  regex_t     idxRegPattern;
L
Liu Jicong 已提交
338 339 340

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

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

350 351
  SArray* actualLog = taosArrayInit(8, sizeof(SWalFileInfo));

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

wafwerar's avatar
wafwerar 已提交
365
  taosCloseDir(&pDir);
L
Liu Jicong 已提交
366 367 368
  regfree(&logRegPattern);
  regfree(&idxRegPattern);

369
  taosArraySort(actualLog, compareWalFileInfo);
L
Liu Jicong 已提交
370

371 372 373 374 375 376 377 378 379 380 381 382 383
  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);
  ASSERT(sz == actualFileNum);
L
Liu Jicong 已提交
384

385 386 387 388
  // scan and determine the lastVer
  int32_t fileIdx = sz;

  while (--fileIdx >= 0) {
L
Liu Jicong 已提交
389
    char          fnameStr[WAL_FILE_LEN];
390 391 392
    int64_t       fileSize = 0;
    SWalFileInfo* pFileInfo = taosArrayGet(pWal->fileInfoSet, fileIdx);

L
Liu Jicong 已提交
393
    walBuildLogName(pWal, pFileInfo->firstVer, fnameStr);
394 395 396 397 398
    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 已提交
399 400
    }

401 402 403 404 405
    ASSERT(pFileInfo->firstVer >= 0);

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

409 410 411 412 413
    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 已提交
414
      }
415 416
      ASSERT(pFileInfo->fileSize == 0);
      // remove the empty wal log, and its idx
417
      wInfo("vgId:%d, wal remove empty file %s", pWal->cfg.vgId, fnameStr);
418 419
      taosRemoveFile(fnameStr);
      walBuildIdxName(pWal, pFileInfo->firstVer, fnameStr);
420
      wInfo("vgId:%d, wal remove empty file %s", pWal->cfg.vgId, fnameStr);
421 422 423 424
      taosRemoveFile(fnameStr);
      // remove its meta entry
      taosArrayRemove(pWal->fileInfoSet, fileIdx);
      continue;
L
Liu Jicong 已提交
425 426
    }

427 428 429
    // update lastVer
    pFileInfo->lastVer = lastVer;
    totSize += pFileInfo->fileSize;
L
Liu Jicong 已提交
430
  }
L
Liu Jicong 已提交
431

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

443 444 445 446
  // update meta file
  if (updateMeta) {
    (void)walSaveMeta(pWal);
  }
447 448 449 450 451

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

452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
  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 已提交
469 470
  }

L
Liu Jicong 已提交
471 472 473
  return 0;
}

474
int walCheckAndRepairIdxFile(SWal* pWal, int32_t fileIdx) {
L
Liu Jicong 已提交
475
  int32_t sz = taosArrayGetSize(pWal->fileInfoSet);
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 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
  ASSERT(fileIdx >= 0 && fileIdx < sz);
  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;
  }

  ASSERT(pFileInfo->fileSize > 0 && pFileInfo->firstVer >= 0 && pFileInfo->lastVer >= pFileInfo->firstVer);
  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) {
521
      wError("vgId:%d, failed to seek file due to %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId, strerror(errno),
522
             offset, fnameStr);
L
Liu Jicong 已提交
523
      terrno = TAOS_SYSTEM_ERROR(errno);
524 525 526 527 528 529 530 531
      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 已提交
532 533
    }

534
    if (idxEntry.ver > pFileInfo->lastVer) {
L
Liu Jicong 已提交
535 536
      continue;
    }
L
Liu Jicong 已提交
537

538 539 540 541
    if (offset != (idxEntry.ver - pFileInfo->firstVer) * sizeof(SWalIdxEntry)) {
      continue;
    }

542 543 544 545
    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 已提交
546 547
    }

548 549
    if (idxEntry.ver == ckHead.head.version) {
      break;
L
Liu Jicong 已提交
550
    }
551 552
  }
  offset += sizeof(SWalIdxEntry);
L
Liu Jicong 已提交
553

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

556 557 558 559 560 561 562 563 564 565 566 567
  // 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) {
568
    wError("vgId:%d, failed to seek file due to %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId, strerror(errno),
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
           offset, fnameStr);
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

  while (idxEntry.ver < pFileInfo->lastVer) {
    ASSERT(idxEntry.ver == ckHead.head.version);

    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 已提交
585
    wWarn("vgId:%d, wal idx append new entry %" PRId64 " %" PRId64, pWal->cfg.vgId, idxEntry.ver, idxEntry.offset);
586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
    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 已提交
614 615
    }
  }
L
Liu Jicong 已提交
616 617 618
  return 0;
}

L
Liu Jicong 已提交
619 620 621 622
int walRollFileInfo(SWal* pWal) {
  int64_t ts = taosGetTimestampSec();

  SArray* pArray = pWal->fileInfoSet;
L
Liu Jicong 已提交
623
  if (taosArrayGetSize(pArray) != 0) {
L
Liu Jicong 已提交
624
    SWalFileInfo* pInfo = taosArrayGetLast(pArray);
L
Liu Jicong 已提交
625
    pInfo->lastVer = pWal->vers.lastVer;
L
Liu Jicong 已提交
626 627 628
    pInfo->closeTs = ts;
  }

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

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

  cJSON_AddItemToObject(pRoot, "files", pFiles);
L
Liu Jicong 已提交
678
  SWalFileInfo* pData = pWal->fileInfoSet->pData;
L
Liu Jicong 已提交
679
  for (int i = 0; i < sz; i++) {
L
Liu Jicong 已提交
680
    SWalFileInfo* pInfo = &pData[i];
681
    cJSON_AddItemToArray(pFiles, pField = cJSON_CreateObject());
L
Liu Jicong 已提交
682
    if (pField == NULL) {
683
      cJSON_Delete(pRoot);
L
Liu Jicong 已提交
684 685
      return NULL;
    }
L
Liu Jicong 已提交
686 687
    // cjson only support int32_t or double
    // string are used to prohibit the loss of precision
688 689 690 691 692 693 694 695 696 697
    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 已提交
698
  }
L
Liu Jicong 已提交
699 700 701
  char* serialized = cJSON_Print(pRoot);
  cJSON_Delete(pRoot);
  return serialized;
L
Liu Jicong 已提交
702 703
}

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

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

_err:
  cJSON_Delete(pRoot);
  return -1;
L
Liu Jicong 已提交
759 760 761
}

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

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

wafwerar's avatar
wafwerar 已提交
772
  TdDirEntryPtr pDirEntry;
L
Liu Jicong 已提交
773

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

791 792 793 794 795 796
void walUpdateSyncedOffset(SWal* pWal) {
  SWalFileInfo* pFileInfo = walGetCurFileInfo(pWal);
  if (pFileInfo == NULL) return;
  pFileInfo->syncedOffset = pFileInfo->fileSize;
}

L
Liu Jicong 已提交
797
int walSaveMeta(SWal* pWal) {
L
Liu Jicong 已提交
798
  int  metaVer = walFindCurMetaVer(pWal);
L
Liu Jicong 已提交
799
  char fnameStr[WAL_FILE_LEN];
800
  char tmpFnameStr[WAL_FILE_LEN];
801 802 803 804 805 806 807 808 809 810 811 812 813 814
  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;
  }
815

816 817 818
  // update synced offset
  (void)walUpdateSyncedOffset(pWal);

819 820 821 822 823
  // flush to a tmpfile
  n = walBuildTmpMetaName(pWal, tmpFnameStr);
  ASSERT(n < sizeof(tmpFnameStr) && "Buffer overflow of file name");

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

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

838
  if (taosFsyncFile(pMetaFile) < 0) {
839
    wError("vgId:%d, failed to sync file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
840 841 842 843 844
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

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

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

  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 已提交
858
  }
L
Liu Jicong 已提交
859 860 861

  // delete old file
  if (metaVer > -1) {
L
Liu Jicong 已提交
862
    walBuildMetaName(pWal, metaVer, fnameStr);
863
    taosRemoveFile(fnameStr);
L
Liu Jicong 已提交
864
  }
wafwerar's avatar
wafwerar 已提交
865
  taosMemoryFree(serialized);
L
Liu Jicong 已提交
866
  return 0;
867 868 869 870 871

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

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

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 已提交
927
  return taosRemoveFile(fnameStr);
928
}