walMeta.c 30.7 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
    pWal->vers.lastVer = pWal->vers.snapshotVer;
  }
292 293 294
  // reset commitVer and appliedVer
  pWal->vers.commitVer = pWal->vers.snapshotVer;
  pWal->vers.appliedVer = pWal->vers.snapshotVer;
295
  wInfo("vgId:%d, reset commitVer to %" PRId64, pWal->cfg.vgId, pWal->vers.commitVer);
296 297
}

298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
int walRepairLogFileTs(SWal* pWal, bool* updateMeta) {
  int32_t sz = taosArrayGetSize(pWal->fileInfoSet);
  int32_t fileIdx = -1;
  int32_t lastCloseTs = 0;
  char    fnameStr[WAL_FILE_LEN] = {0};

  while (++fileIdx < sz - 1) {
    SWalFileInfo* pFileInfo = taosArrayGet(pWal->fileInfoSet, fileIdx);
    if (pFileInfo->closeTs != -1) {
      lastCloseTs = pFileInfo->closeTs;
      continue;
    }

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

    if (updateMeta != NULL) *updateMeta = true;
    if (pFileInfo->createTs == -1) pFileInfo->createTs = lastCloseTs;
    pFileInfo->closeTs = mtime;
    lastCloseTs = pFileInfo->closeTs;
  }

  return 0;
}

328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
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;
}

355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
int walTrimIdxFile(SWal* pWal, int32_t fileIdx) {
  SWalFileInfo* pFileInfo = taosArrayGet(pWal->fileInfoSet, fileIdx);
  ASSERT(pFileInfo != NULL);
  char fnameStr[WAL_FILE_LEN];
  walBuildIdxName(pWal, pFileInfo->firstVer, fnameStr);

  int64_t fileSize = 0;
  taosStatFile(fnameStr, &fileSize, NULL);
  int64_t records = TMAX(0, pFileInfo->lastVer - pFileInfo->firstVer + 1);
  int64_t lastEndOffset = records * sizeof(SWalIdxEntry);

  if (fileSize <= lastEndOffset) {
    return 0;
  }

  TdFilePtr pFile = taosOpenFile(fnameStr, TD_FILE_READ | TD_FILE_WRITE);
  if (pFile == NULL) {
    terrno = TAOS_SYSTEM_ERROR(errno);
    return -1;
  }

  wInfo("vgId:%d, trim idx file. file: %s, size: %" PRId64 ", offset: %" PRId64, pWal->cfg.vgId, fnameStr, fileSize,
        lastEndOffset);

  taosFtruncateFile(pFile, lastEndOffset);
  taosCloseFile(&pFile);
  return 0;
}

L
Liu Jicong 已提交
384 385 386 387
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 已提交
388 389
  regex_t     logRegPattern;
  regex_t     idxRegPattern;
L
Liu Jicong 已提交
390 391 392

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

wafwerar's avatar
wafwerar 已提交
394 395
  TdDirPtr pDir = taosOpenDir(pWal->path);
  if (pDir == NULL) {
L
Liu Jicong 已提交
396 397
    regfree(&logRegPattern);
    regfree(&idxRegPattern);
L
Liu Jicong 已提交
398 399 400 401
    wError("vgId:%d, path:%s, failed to open since %s", pWal->cfg.vgId, pWal->path, strerror(errno));
    return -1;
  }

402 403
  SArray* actualLog = taosArrayInit(8, sizeof(SWalFileInfo));

L
Liu Jicong 已提交
404
  // scan log files and build new meta
wafwerar's avatar
wafwerar 已提交
405 406 407
  TdDirEntryPtr pDirEntry;
  while ((pDirEntry = taosReadDir(pDir)) != NULL) {
    char* name = taosDirEntryBaseName(taosGetDirEntryName(pDirEntry));
L
Liu Jicong 已提交
408 409
    int   code = regexec(&logRegPattern, name, 0, NULL, 0);
    if (code == 0) {
L
Liu Jicong 已提交
410 411 412
      SWalFileInfo fileInfo;
      memset(&fileInfo, -1, sizeof(SWalFileInfo));
      sscanf(name, "%" PRId64 ".log", &fileInfo.firstVer);
413
      taosArrayPush(actualLog, &fileInfo);
L
Liu Jicong 已提交
414 415 416
    }
  }

wafwerar's avatar
wafwerar 已提交
417
  taosCloseDir(&pDir);
L
Liu Jicong 已提交
418 419 420
  regfree(&logRegPattern);
  regfree(&idxRegPattern);

421
  taosArraySort(actualLog, compareWalFileInfo);
L
Liu Jicong 已提交
422

423 424 425 426 427 428 429 430 431 432 433 434
  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 已提交
435

436 437 438 439
  // scan and determine the lastVer
  int32_t fileIdx = sz;

  while (--fileIdx >= 0) {
L
Liu Jicong 已提交
440
    char          fnameStr[WAL_FILE_LEN];
441 442 443
    int64_t       fileSize = 0;
    SWalFileInfo* pFileInfo = taosArrayGet(pWal->fileInfoSet, fileIdx);

L
Liu Jicong 已提交
444
    walBuildLogName(pWal, pFileInfo->firstVer, fnameStr);
445 446 447 448 449
    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 已提交
450 451
    }

452 453 454
    if (pFileInfo->lastVer >= pFileInfo->firstVer && fileSize == pFileInfo->fileSize) {
      totSize += pFileInfo->fileSize;
      continue;
L
Liu Jicong 已提交
455
    }
456
    updateMeta = true;
L
Liu Jicong 已提交
457

458 459
    (void)walTrimIdxFile(pWal, fileIdx);

460 461 462 463 464
    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 已提交
465
      }
466 467
      // empty log file
      lastVer = pFileInfo->firstVer - 1;
L
Liu Jicong 已提交
468 469
    }

470 471 472
    // update lastVer
    pFileInfo->lastVer = lastVer;
    totSize += pFileInfo->fileSize;
L
Liu Jicong 已提交
473
  }
L
Liu Jicong 已提交
474

475
  // reset vers info and so on
L
Liu Jicong 已提交
476
  actualFileNum = taosArrayGetSize(pWal->fileInfoSet);
L
Liu Jicong 已提交
477
  pWal->writeCur = actualFileNum - 1;
478 479
  pWal->totSize = totSize;
  pWal->vers.lastVer = -1;
L
Liu Jicong 已提交
480
  if (actualFileNum > 0) {
481 482
    pWal->vers.firstVer = ((SWalFileInfo*)taosArrayGet(pWal->fileInfoSet, 0))->firstVer;
    pWal->vers.lastVer = ((SWalFileInfo*)taosArrayGetLast(pWal->fileInfoSet))->lastVer;
L
Liu Jicong 已提交
483
  }
484
  (void)walAlignVersions(pWal);
L
Liu Jicong 已提交
485

486 487 488 489 490
  // repair ts of files
  if (walRepairLogFileTs(pWal, &updateMeta) < 0) {
    return -1;
  }

491 492 493 494
  // update meta file
  if (updateMeta) {
    (void)walSaveMeta(pWal);
  }
495 496 497 498 499

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

500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
  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 已提交
517 518
  }

L
Liu Jicong 已提交
519 520 521
  return 0;
}

522
int walCheckAndRepairIdxFile(SWal* pWal, int32_t fileIdx) {
L
Liu Jicong 已提交
523
  int32_t       sz = taosArrayGetSize(pWal->fileInfoSet);
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
  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) {
567
      wError("vgId:%d, failed to seek file due to %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId, strerror(errno),
568
             offset, fnameStr);
L
Liu Jicong 已提交
569
      terrno = TAOS_SYSTEM_ERROR(errno);
570 571 572 573 574 575 576 577
      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 已提交
578 579
    }

580
    if (idxEntry.ver > pFileInfo->lastVer) {
L
Liu Jicong 已提交
581 582
      continue;
    }
L
Liu Jicong 已提交
583

584 585 586 587
    if (offset != (idxEntry.ver - pFileInfo->firstVer) * sizeof(SWalIdxEntry)) {
      continue;
    }

588 589 590 591
    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 已提交
592 593
    }

594 595
    if (idxEntry.ver == ckHead.head.version) {
      break;
L
Liu Jicong 已提交
596
    }
597 598
  }
  offset += sizeof(SWalIdxEntry);
L
Liu Jicong 已提交
599

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

602 603 604 605
  // ftruncate idx file
  if (offset < fileSize) {
    if (taosFtruncateFile(pIdxFile, offset) < 0) {
      terrno = TAOS_SYSTEM_ERROR(errno);
606 607
      wError("vgId:%d, failed to ftruncate file since %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId, terrstr(),
             offset, fnameStr);
608 609 610 611 612 613 614
      goto _err;
    }
  }

  // rebuild idx file
  if (taosLSeekFile(pIdxFile, 0, SEEK_END) < 0) {
    terrno = TAOS_SYSTEM_ERROR(errno);
615 616
    wError("vgId:%d, failed to seek file since %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId, terrstr(), offset,
           fnameStr);
617 618 619
    goto _err;
  }

620
  int64_t count = 0;
621
  while (idxEntry.ver < pFileInfo->lastVer) {
L
Liu Jicong 已提交
622
    /*A(idxEntry.ver == ckHead.head.version);*/
623 624 625 626 627

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

    if (walReadLogHead(pLogFile, idxEntry.offset, &ckHead) < 0) {
628 629
      wError("vgId:%d, failed to read wal log head since %s. index:%" PRId64 ", offset:%" PRId64 ", file:%s",
             pWal->cfg.vgId, terrstr(), idxEntry.ver, idxEntry.offset, fLogNameStr);
630 631 632
      goto _err;
    }
    if (taosWriteFile(pIdxFile, &idxEntry, sizeof(SWalIdxEntry)) < 0) {
633
      terrno = TAOS_SYSTEM_ERROR(errno);
634 635 636
      wError("vgId:%d, failed to append file since %s. file:%s", pWal->cfg.vgId, terrstr(), fnameStr);
      goto _err;
    }
637
    count++;
638 639 640
  }

  if (taosFsyncFile(pIdxFile) < 0) {
641
    terrno = TAOS_SYSTEM_ERROR(errno);
642 643 644 645
    wError("vgId:%d, faild to fsync file since %s. file:%s", pWal->cfg.vgId, terrstr(), fnameStr);
    goto _err;
  }

646 647 648 649 650
  if (count > 0) {
    wInfo("vgId:%d, rebuilt %" PRId64 " wal idx entries until lastVer: %" PRId64, pWal->cfg.vgId, count,
          pFileInfo->lastVer);
  }

651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
  (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 已提交
668 669
    }
  }
L
Liu Jicong 已提交
670 671 672
  return 0;
}

L
Liu Jicong 已提交
673 674 675 676
int walRollFileInfo(SWal* pWal) {
  int64_t ts = taosGetTimestampSec();

  SArray* pArray = pWal->fileInfoSet;
L
Liu Jicong 已提交
677
  if (taosArrayGetSize(pArray) != 0) {
L
Liu Jicong 已提交
678
    SWalFileInfo* pInfo = taosArrayGetLast(pArray);
L
Liu Jicong 已提交
679
    pInfo->lastVer = pWal->vers.lastVer;
L
Liu Jicong 已提交
680 681 682
    pInfo->closeTs = ts;
  }

L
Liu Jicong 已提交
683
  // TODO: change to emplace back
wafwerar's avatar
wafwerar 已提交
684
  SWalFileInfo* pNewInfo = taosMemoryMalloc(sizeof(SWalFileInfo));
L
Liu Jicong 已提交
685
  if (pNewInfo == NULL) {
S
Shengliang Guan 已提交
686
    terrno = TSDB_CODE_OUT_OF_MEMORY;
L
Liu Jicong 已提交
687 688
    return -1;
  }
L
Liu Jicong 已提交
689
  pNewInfo->firstVer = pWal->vers.lastVer + 1;
L
Liu Jicong 已提交
690 691 692 693
  pNewInfo->lastVer = -1;
  pNewInfo->createTs = ts;
  pNewInfo->closeTs = -1;
  pNewInfo->fileSize = 0;
694
  pNewInfo->syncedOffset = 0;
L
Liu Jicong 已提交
695
  taosArrayPush(pArray, pNewInfo);
wafwerar's avatar
wafwerar 已提交
696
  taosMemoryFree(pNewInfo);
L
Liu Jicong 已提交
697 698 699
  return 0;
}

700
char* walMetaSerialize(SWal* pWal) {
L
Liu Jicong 已提交
701
  char   buf[30];
L
Liu Jicong 已提交
702
  int    sz = taosArrayGetSize(pWal->fileInfoSet);
703 704 705 706
  cJSON* pRoot = cJSON_CreateObject();
  cJSON* pMeta = cJSON_CreateObject();
  cJSON* pFiles = cJSON_CreateArray();
  cJSON* pField;
L
Liu Jicong 已提交
707
  if (pRoot == NULL || pMeta == NULL || pFiles == NULL) {
L
Liu Jicong 已提交
708
    if (pRoot) {
L
Liu Jicong 已提交
709 710
      cJSON_Delete(pRoot);
    }
L
Liu Jicong 已提交
711
    if (pMeta) {
L
Liu Jicong 已提交
712 713
      cJSON_Delete(pMeta);
    }
L
Liu Jicong 已提交
714
    if (pFiles) {
L
Liu Jicong 已提交
715 716
      cJSON_Delete(pFiles);
    }
S
Shengliang Guan 已提交
717
    terrno = TSDB_CODE_OUT_OF_MEMORY;
L
Liu Jicong 已提交
718 719
    return NULL;
  }
720
  cJSON_AddItemToObject(pRoot, "meta", pMeta);
L
Liu Jicong 已提交
721
  sprintf(buf, "%" PRId64, pWal->vers.firstVer);
722
  cJSON_AddStringToObject(pMeta, "firstVer", buf);
L
Liu Jicong 已提交
723
  sprintf(buf, "%" PRId64, pWal->vers.snapshotVer);
724
  cJSON_AddStringToObject(pMeta, "snapshotVer", buf);
L
Liu Jicong 已提交
725
  sprintf(buf, "%" PRId64, pWal->vers.commitVer);
726
  cJSON_AddStringToObject(pMeta, "commitVer", buf);
L
Liu Jicong 已提交
727
  sprintf(buf, "%" PRId64, pWal->vers.lastVer);
728 729 730
  cJSON_AddStringToObject(pMeta, "lastVer", buf);

  cJSON_AddItemToObject(pRoot, "files", pFiles);
L
Liu Jicong 已提交
731
  SWalFileInfo* pData = pWal->fileInfoSet->pData;
L
Liu Jicong 已提交
732
  for (int i = 0; i < sz; i++) {
L
Liu Jicong 已提交
733
    SWalFileInfo* pInfo = &pData[i];
734
    cJSON_AddItemToArray(pFiles, pField = cJSON_CreateObject());
L
Liu Jicong 已提交
735
    if (pField == NULL) {
736
      cJSON_Delete(pRoot);
L
Liu Jicong 已提交
737 738
      return NULL;
    }
L
Liu Jicong 已提交
739 740
    // cjson only support int32_t or double
    // string are used to prohibit the loss of precision
741 742 743 744 745 746 747 748 749 750
    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 已提交
751
  }
L
Liu Jicong 已提交
752 753 754
  char* serialized = cJSON_Print(pRoot);
  cJSON_Delete(pRoot);
  return serialized;
L
Liu Jicong 已提交
755 756
}

757
int walMetaDeserialize(SWal* pWal, const char* bytes) {
L
Liu Jicong 已提交
758
  /*A(taosArrayGetSize(pWal->fileInfoSet) == 0);*/
759 760
  cJSON *pRoot, *pMeta, *pFiles, *pInfoJson, *pField;
  pRoot = cJSON_Parse(bytes);
761
  if (!pRoot) goto _err;
762
  pMeta = cJSON_GetObjectItem(pRoot, "meta");
763
  if (!pMeta) goto _err;
764
  pField = cJSON_GetObjectItem(pMeta, "firstVer");
765
  if (!pField) goto _err;
L
Liu Jicong 已提交
766
  pWal->vers.firstVer = atoll(cJSON_GetStringValue(pField));
767
  pField = cJSON_GetObjectItem(pMeta, "snapshotVer");
768
  if (!pField) goto _err;
L
Liu Jicong 已提交
769
  pWal->vers.snapshotVer = atoll(cJSON_GetStringValue(pField));
770
  pField = cJSON_GetObjectItem(pMeta, "commitVer");
771
  if (!pField) goto _err;
L
Liu Jicong 已提交
772
  pWal->vers.commitVer = atoll(cJSON_GetStringValue(pField));
773
  pField = cJSON_GetObjectItem(pMeta, "lastVer");
774
  if (!pField) goto _err;
L
Liu Jicong 已提交
775
  pWal->vers.lastVer = atoll(cJSON_GetStringValue(pField));
776 777 778

  pFiles = cJSON_GetObjectItem(pRoot, "files");
  int sz = cJSON_GetArraySize(pFiles);
L
Liu Jicong 已提交
779
  // deserialize
L
Liu Jicong 已提交
780 781
  SArray* pArray = pWal->fileInfoSet;
  taosArrayEnsureCap(pArray, sz);
782

L
Liu Jicong 已提交
783
  for (int i = 0; i < sz; i++) {
784
    pInfoJson = cJSON_GetArrayItem(pFiles, i);
785
    if (!pInfoJson) goto _err;
786 787 788

    SWalFileInfo info = {0};

L
Liu Jicong 已提交
789
    pField = cJSON_GetObjectItem(pInfoJson, "firstVer");
790
    if (!pField) goto _err;
791
    info.firstVer = atoll(cJSON_GetStringValue(pField));
L
Liu Jicong 已提交
792
    pField = cJSON_GetObjectItem(pInfoJson, "lastVer");
793
    if (!pField) goto _err;
794
    info.lastVer = atoll(cJSON_GetStringValue(pField));
L
Liu Jicong 已提交
795
    pField = cJSON_GetObjectItem(pInfoJson, "createTs");
796
    if (!pField) goto _err;
797
    info.createTs = atoll(cJSON_GetStringValue(pField));
L
Liu Jicong 已提交
798
    pField = cJSON_GetObjectItem(pInfoJson, "closeTs");
799
    if (!pField) goto _err;
800
    info.closeTs = atoll(cJSON_GetStringValue(pField));
L
Liu Jicong 已提交
801
    pField = cJSON_GetObjectItem(pInfoJson, "fileSize");
802
    if (!pField) goto _err;
803 804
    info.fileSize = atoll(cJSON_GetStringValue(pField));
    taosArrayPush(pArray, &info);
L
Liu Jicong 已提交
805
  }
806
  pWal->fileInfoSet = pArray;
L
Liu Jicong 已提交
807
  pWal->writeCur = sz - 1;
L
Liu Jicong 已提交
808
  cJSON_Delete(pRoot);
809
  return 0;
810 811 812 813

_err:
  cJSON_Delete(pRoot);
  return -1;
L
Liu Jicong 已提交
814 815 816
}

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

wafwerar's avatar
wafwerar 已提交
821 822
  TdDirPtr pDir = taosOpenDir(pWal->path);
  if (pDir == NULL) {
L
Liu Jicong 已提交
823
    wError("vgId:%d, path:%s, failed to open since %s", pWal->cfg.vgId, pWal->path, strerror(errno));
L
Liu Jicong 已提交
824 825 826
    return -1;
  }

wafwerar's avatar
wafwerar 已提交
827
  TdDirEntryPtr pDirEntry;
L
Liu Jicong 已提交
828

L
Liu Jicong 已提交
829
  // find existing meta-ver[x].json
L
Liu Jicong 已提交
830
  int metaVer = -1;
wafwerar's avatar
wafwerar 已提交
831 832
  while ((pDirEntry = taosReadDir(pDir)) != NULL) {
    char* name = taosDirEntryBaseName(taosGetDirEntryName(pDirEntry));
L
Liu Jicong 已提交
833 834
    int   code = regexec(&walMetaRegexPattern, name, 0, NULL, 0);
    if (code == 0) {
L
Liu Jicong 已提交
835
      sscanf(name, "meta-ver%d", &metaVer);
L
Liu Jicong 已提交
836
      wDebug("vgId:%d, wal find current meta: %s is the meta file, ver %d", pWal->cfg.vgId, name, metaVer);
L
Liu Jicong 已提交
837 838
      break;
    }
L
Liu Jicong 已提交
839
    wDebug("vgId:%d, wal find current meta: %s is not meta file", pWal->cfg.vgId, name);
L
Liu Jicong 已提交
840
  }
wafwerar's avatar
wafwerar 已提交
841
  taosCloseDir(&pDir);
L
Liu Jicong 已提交
842
  regfree(&walMetaRegexPattern);
L
Liu Jicong 已提交
843 844 845
  return metaVer;
}

846 847 848 849 850 851
void walUpdateSyncedOffset(SWal* pWal) {
  SWalFileInfo* pFileInfo = walGetCurFileInfo(pWal);
  if (pFileInfo == NULL) return;
  pFileInfo->syncedOffset = pFileInfo->fileSize;
}

L
Liu Jicong 已提交
852
int walSaveMeta(SWal* pWal) {
L
Liu Jicong 已提交
853
  int  metaVer = walFindCurMetaVer(pWal);
L
Liu Jicong 已提交
854
  char fnameStr[WAL_FILE_LEN];
855
  char tmpFnameStr[WAL_FILE_LEN];
856 857 858 859 860 861 862 863 864 865 866 867 868 869
  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;
  }
870

871 872 873
  // update synced offset
  (void)walUpdateSyncedOffset(pWal);

874 875
  // flush to a tmpfile
  n = walBuildTmpMetaName(pWal, tmpFnameStr);
L
Liu Jicong 已提交
876
  if (n >= sizeof(tmpFnameStr)) {
L
Liu Jicong 已提交
877 878
    return -1;
  }
879 880

  TdFilePtr pMetaFile = taosOpenFile(tmpFnameStr, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
L
Liu Jicong 已提交
881
  if (pMetaFile == NULL) {
882
    wError("vgId:%d, failed to open file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
883
    terrno = TAOS_SYSTEM_ERROR(errno);
L
Liu Jicong 已提交
884 885
    return -1;
  }
886

887
  char* serialized = walMetaSerialize(pWal);
L
Liu Jicong 已提交
888
  int   len = strlen(serialized);
L
Liu Jicong 已提交
889
  if (len != taosWriteFile(pMetaFile, serialized, len)) {
890
    wError("vgId:%d, failed to write file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
891 892 893
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }
L
Liu Jicong 已提交
894

895
  if (taosFsyncFile(pMetaFile) < 0) {
896
    wError("vgId:%d, failed to sync file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
897 898 899 900 901
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

  if (taosCloseFile(&pMetaFile) < 0) {
902
    wError("vgId:%d, failed to close file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
903 904 905 906 907 908
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

  // rename it
  n = walBuildMetaName(pWal, metaVer + 1, fnameStr);
L
Liu Jicong 已提交
909
  if (n >= sizeof(fnameStr)) {
L
Liu Jicong 已提交
910 911
    goto _err;
  }
912 913 914 915 916

  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 已提交
917
  }
L
Liu Jicong 已提交
918 919 920

  // delete old file
  if (metaVer > -1) {
L
Liu Jicong 已提交
921
    walBuildMetaName(pWal, metaVer, fnameStr);
922
    taosRemoveFile(fnameStr);
L
Liu Jicong 已提交
923
  }
wafwerar's avatar
wafwerar 已提交
924
  taosMemoryFree(serialized);
L
Liu Jicong 已提交
925
  return 0;
926 927 928 929 930

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

L
Liu Jicong 已提交
933
int walLoadMeta(SWal* pWal) {
L
Liu Jicong 已提交
934
  // find existing meta file
L
Liu Jicong 已提交
935
  int metaVer = walFindCurMetaVer(pWal);
L
Liu Jicong 已提交
936
  if (metaVer == -1) {
S
Shengliang Guan 已提交
937
    wDebug("vgId:%d, wal find meta ver %d", pWal->cfg.vgId, metaVer);
L
Liu Jicong 已提交
938
    return -1;
L
Liu Jicong 已提交
939 940 941
  }
  char fnameStr[WAL_FILE_LEN];
  walBuildMetaName(pWal, metaVer, fnameStr);
L
Liu Jicong 已提交
942
  // read metafile
L
Liu Jicong 已提交
943 944
  int64_t fileSize = 0;
  taosStatFile(fnameStr, &fileSize, NULL);
L
Liu Jicong 已提交
945
  if (fileSize == 0) {
946
    (void)taosRemoveFile(fnameStr);
S
Shengliang Guan 已提交
947
    wDebug("vgId:%d, wal find empty meta ver %d", pWal->cfg.vgId, metaVer);
L
Liu Jicong 已提交
948 949
    return -1;
  }
L
Liu Jicong 已提交
950
  int   size = (int)fileSize;
wafwerar's avatar
wafwerar 已提交
951
  char* buf = taosMemoryMalloc(size + 5);
L
Liu Jicong 已提交
952
  if (buf == NULL) {
S
Shengliang Guan 已提交
953
    terrno = TSDB_CODE_OUT_OF_MEMORY;
L
Liu Jicong 已提交
954 955
    return -1;
  }
L
Liu Jicong 已提交
956
  memset(buf, 0, size + 5);
957 958
  TdFilePtr pFile = taosOpenFile(fnameStr, TD_FILE_READ);
  if (pFile == NULL) {
L
Liu Jicong 已提交
959
    terrno = TSDB_CODE_WAL_FILE_CORRUPTED;
L
Liu Jicong 已提交
960
    taosMemoryFree(buf);
L
Liu Jicong 已提交
961 962
    return -1;
  }
963
  if (taosReadFile(pFile, buf, size) != size) {
L
Liu Jicong 已提交
964
    terrno = TAOS_SYSTEM_ERROR(errno);
965
    taosCloseFile(&pFile);
wafwerar's avatar
wafwerar 已提交
966
    taosMemoryFree(buf);
L
Liu Jicong 已提交
967 968
    return -1;
  }
L
Liu Jicong 已提交
969
  // load into fileInfoSet
970
  int code = walMetaDeserialize(pWal, buf);
971 972 973 974
  if (code < 0) {
    wError("failed to deserialize wal meta. file:%s", fnameStr);
    terrno = TSDB_CODE_WAL_FILE_CORRUPTED;
  }
975
  taosCloseFile(&pFile);
wafwerar's avatar
wafwerar 已提交
976
  taosMemoryFree(buf);
L
Liu Jicong 已提交
977
  return code;
L
Liu Jicong 已提交
978
}
979 980 981 982 983 984

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