walMeta.c 29.5 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
bool FORCE_INLINE walIsEmpty(SWal* pWal) {
L
Liu Jicong 已提交
28
  return (pWal->vers.firstVer == -1 || pWal->vers.lastVer < pWal->vers.firstVer);  // [firstVer, lastVer + 1)
29
}
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;
L
Liu Jicong 已提交
52

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

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

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

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

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

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

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

103 104 105 106 107
    readSize = end - offset;
    capacity = readSize + sizeof(magic);

    void* ptr = taosMemoryRealloc(buf, capacity);
    if (ptr == NULL) {
S
Shengliang Guan 已提交
108
      terrno = TSDB_CODE_OUT_OF_MEMORY;
109 110 111
      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
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);
      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) {
279 280
  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,
281
          pWal->vers.firstVer, pWal->vers.snapshotVer);
282
    pWal->vers.firstVer = pWal->vers.snapshotVer + 1;
283 284
  }
  if (pWal->vers.lastVer < pWal->vers.snapshotVer) {
285
    wWarn("vgId:%d, lastVer:%" PRId64 " is less than snapshotVer:%" PRId64 ". align with it.", pWal->cfg.vgId,
286
          pWal->vers.lastVer, pWal->vers.snapshotVer);
287 288 289
    if (pWal->vers.lastVer < pWal->vers.firstVer) {
      pWal->vers.firstVer = pWal->vers.snapshotVer + 1;
    }
290 291 292
    pWal->vers.lastVer = pWal->vers.snapshotVer;
  }
  if (pWal->vers.commitVer < pWal->vers.snapshotVer) {
293
    wWarn("vgId:%d, commitVer:%" PRId64 " is less than snapshotVer:%" PRId64 ". align with it.", pWal->cfg.vgId,
294 295 296 297
          pWal->vers.commitVer, pWal->vers.snapshotVer);
    pWal->vers.commitVer = pWal->vers.snapshotVer;
  }
  if (pWal->vers.appliedVer < pWal->vers.snapshotVer) {
298
    wWarn("vgId:%d, appliedVer:%" PRId64 " is less than snapshotVer:%" PRId64 ". align with it.", pWal->cfg.vgId,
299 300 301 302 303 304 305 306
          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);
}

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 332 333
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 已提交
334 335 336 337
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 已提交
338 339
  regex_t     logRegPattern;
  regex_t     idxRegPattern;
L
Liu Jicong 已提交
340 341 342

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

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

352 353
  SArray* actualLog = taosArrayInit(8, sizeof(SWalFileInfo));

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

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

371
  taosArraySort(actualLog, compareWalFileInfo);
L
Liu Jicong 已提交
372

373 374 375 376 377 378 379 380 381 382 383 384
  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);
L
Liu Jicong 已提交
385

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

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

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

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

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

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

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

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

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

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

L
Liu Jicong 已提交
469 470 471
  return 0;
}

472
int walCheckAndRepairIdxFile(SWal* pWal, int32_t fileIdx) {
L
Liu Jicong 已提交
473
  int32_t       sz = taosArrayGetSize(pWal->fileInfoSet);
474 475 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
  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;
  }

  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) {
517
      wError("vgId:%d, failed to seek file due to %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId, strerror(errno),
518
             offset, fnameStr);
L
Liu Jicong 已提交
519
      terrno = TAOS_SYSTEM_ERROR(errno);
520 521 522 523 524 525 526 527
      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 已提交
528 529
    }

530
    if (idxEntry.ver > pFileInfo->lastVer) {
L
Liu Jicong 已提交
531 532
      continue;
    }
L
Liu Jicong 已提交
533

534 535 536 537
    if (offset != (idxEntry.ver - pFileInfo->firstVer) * sizeof(SWalIdxEntry)) {
      continue;
    }

538 539 540 541
    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 已提交
542 543
    }

544 545
    if (idxEntry.ver == ckHead.head.version) {
      break;
L
Liu Jicong 已提交
546
    }
547 548
  }
  offset += sizeof(SWalIdxEntry);
L
Liu Jicong 已提交
549

L
Liu Jicong 已提交
550
  /*A(offset == (idxEntry.ver - pFileInfo->firstVer + 1) * sizeof(SWalIdxEntry));*/
551

552 553 554 555 556 557 558 559 560 561 562 563
  // 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) {
564
    wError("vgId:%d, failed to seek file due to %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId, strerror(errno),
565 566 567 568 569 570
           offset, fnameStr);
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

  while (idxEntry.ver < pFileInfo->lastVer) {
L
Liu Jicong 已提交
571
    /*A(idxEntry.ver == ckHead.head.version);*/
572 573 574 575 576 577 578 579 580

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

L
Liu Jicong 已提交
615 616 617 618
int walRollFileInfo(SWal* pWal) {
  int64_t ts = taosGetTimestampSec();

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

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

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

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

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

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

_err:
  cJSON_Delete(pRoot);
  return -1;
L
Liu Jicong 已提交
754 755 756
}

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

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

wafwerar's avatar
wafwerar 已提交
767
  TdDirEntryPtr pDirEntry;
L
Liu Jicong 已提交
768

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

786 787 788 789 790 791
void walUpdateSyncedOffset(SWal* pWal) {
  SWalFileInfo* pFileInfo = walGetCurFileInfo(pWal);
  if (pFileInfo == NULL) return;
  pFileInfo->syncedOffset = pFileInfo->fileSize;
}

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

811 812 813
  // update synced offset
  (void)walUpdateSyncedOffset(pWal);

814 815
  // flush to a tmpfile
  n = walBuildTmpMetaName(pWal, tmpFnameStr);
L
Liu Jicong 已提交
816
  if (n >= sizeof(tmpFnameStr)) {
L
Liu Jicong 已提交
817 818
    return -1;
  }
819 820

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

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

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

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

  // rename it
  n = walBuildMetaName(pWal, metaVer + 1, fnameStr);
L
Liu Jicong 已提交
849
  if (n >= sizeof(fnameStr)) {
L
Liu Jicong 已提交
850 851
    goto _err;
  }
852 853 854 855 856

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

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

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

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

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