walMeta.c 30.4 KB
Newer Older
L
Liu Jicong 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  taosArrayClear(metaLogList);

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

void walAlignVersions(SWal* pWal) {
282 283
  if (pWal->vers.firstVer > pWal->vers.snapshotVer + 1) {
    wWarn("vgId:%d, firstVer:%" PRId64 " is larger than snapshotVer:%" PRId64 " + 1. align with it.", pWal->cfg.vgId,
284
          pWal->vers.firstVer, pWal->vers.snapshotVer);
285
    pWal->vers.firstVer = pWal->vers.snapshotVer + 1;
286 287
  }
  if (pWal->vers.lastVer < pWal->vers.snapshotVer) {
288
    wWarn("vgId:%d, lastVer:%" PRId64 " is less than snapshotVer:%" PRId64 ". align with it.", pWal->cfg.vgId,
289
          pWal->vers.lastVer, pWal->vers.snapshotVer);
290 291 292
    if (pWal->vers.lastVer < pWal->vers.firstVer) {
      pWal->vers.firstVer = pWal->vers.snapshotVer + 1;
    }
293 294
    pWal->vers.lastVer = pWal->vers.snapshotVer;
  }
295 296 297
  // reset commitVer and appliedVer
  pWal->vers.commitVer = pWal->vers.snapshotVer;
  pWal->vers.appliedVer = pWal->vers.snapshotVer;
298
  wInfo("vgId:%d, reset commitVer to %" PRId64, pWal->cfg.vgId, pWal->vers.commitVer);
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
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;
}

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 355 356
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 已提交
357 358 359 360
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 已提交
361 362
  regex_t     logRegPattern;
  regex_t     idxRegPattern;
L
Liu Jicong 已提交
363 364 365

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

wafwerar's avatar
wafwerar 已提交
367 368
  TdDirPtr pDir = taosOpenDir(pWal->path);
  if (pDir == NULL) {
L
Liu Jicong 已提交
369 370
    regfree(&logRegPattern);
    regfree(&idxRegPattern);
L
Liu Jicong 已提交
371 372 373 374
    wError("vgId:%d, path:%s, failed to open since %s", pWal->cfg.vgId, pWal->path, strerror(errno));
    return -1;
  }

375 376
  SArray* actualLog = taosArrayInit(8, sizeof(SWalFileInfo));

L
Liu Jicong 已提交
377
  // scan log files and build new meta
wafwerar's avatar
wafwerar 已提交
378 379 380
  TdDirEntryPtr pDirEntry;
  while ((pDirEntry = taosReadDir(pDir)) != NULL) {
    char* name = taosDirEntryBaseName(taosGetDirEntryName(pDirEntry));
L
Liu Jicong 已提交
381 382
    int   code = regexec(&logRegPattern, name, 0, NULL, 0);
    if (code == 0) {
L
Liu Jicong 已提交
383 384 385
      SWalFileInfo fileInfo;
      memset(&fileInfo, -1, sizeof(SWalFileInfo));
      sscanf(name, "%" PRId64 ".log", &fileInfo.firstVer);
386
      taosArrayPush(actualLog, &fileInfo);
L
Liu Jicong 已提交
387 388 389
    }
  }

wafwerar's avatar
wafwerar 已提交
390
  taosCloseDir(&pDir);
L
Liu Jicong 已提交
391 392 393
  regfree(&logRegPattern);
  regfree(&idxRegPattern);

394
  taosArraySort(actualLog, compareWalFileInfo);
L
Liu Jicong 已提交
395

396 397 398 399 400 401 402 403 404 405 406 407
  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);
408
  ASSERT(sz == actualFileNum);
L
Liu Jicong 已提交
409

410 411 412 413
  // scan and determine the lastVer
  int32_t fileIdx = sz;

  while (--fileIdx >= 0) {
L
Liu Jicong 已提交
414
    char          fnameStr[WAL_FILE_LEN];
415 416 417
    int64_t       fileSize = 0;
    SWalFileInfo* pFileInfo = taosArrayGet(pWal->fileInfoSet, fileIdx);

L
Liu Jicong 已提交
418
    walBuildLogName(pWal, pFileInfo->firstVer, fnameStr);
419 420 421 422 423
    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 已提交
424 425
    }

426
    ASSERT(pFileInfo->firstVer >= 0);
427 428 429 430

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

434 435
    (void)walTrimIdxFile(pWal, fileIdx);

436 437 438 439 440
    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 已提交
441
      }
442
      ASSERT(pFileInfo->fileSize == 0);
443
      // remove the empty wal log, and its idx
444
      wInfo("vgId:%d, wal remove empty file %s", pWal->cfg.vgId, fnameStr);
445 446
      taosRemoveFile(fnameStr);
      walBuildIdxName(pWal, pFileInfo->firstVer, fnameStr);
447
      wInfo("vgId:%d, wal remove empty file %s", pWal->cfg.vgId, fnameStr);
448 449 450 451
      taosRemoveFile(fnameStr);
      // remove its meta entry
      taosArrayRemove(pWal->fileInfoSet, fileIdx);
      continue;
L
Liu Jicong 已提交
452 453
    }

454 455 456
    // update lastVer
    pFileInfo->lastVer = lastVer;
    totSize += pFileInfo->fileSize;
L
Liu Jicong 已提交
457
  }
L
Liu Jicong 已提交
458

459
  // reset vers info and so on
L
Liu Jicong 已提交
460
  actualFileNum = taosArrayGetSize(pWal->fileInfoSet);
L
Liu Jicong 已提交
461
  pWal->writeCur = actualFileNum - 1;
462 463
  pWal->totSize = totSize;
  pWal->vers.lastVer = -1;
L
Liu Jicong 已提交
464
  if (actualFileNum > 0) {
465 466
    pWal->vers.firstVer = ((SWalFileInfo*)taosArrayGet(pWal->fileInfoSet, 0))->firstVer;
    pWal->vers.lastVer = ((SWalFileInfo*)taosArrayGetLast(pWal->fileInfoSet))->lastVer;
L
Liu Jicong 已提交
467
  }
468
  (void)walAlignVersions(pWal);
L
Liu Jicong 已提交
469

470 471 472 473
  // update meta file
  if (updateMeta) {
    (void)walSaveMeta(pWal);
  }
474 475 476 477 478

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

479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
  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 已提交
496 497
  }

L
Liu Jicong 已提交
498 499 500
  return 0;
}

501
int walCheckAndRepairIdxFile(SWal* pWal, int32_t fileIdx) {
L
Liu Jicong 已提交
502
  int32_t sz = taosArrayGetSize(pWal->fileInfoSet);
503
  ASSERT(fileIdx >= 0 && fileIdx < sz);
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;
  }

517
  ASSERT(pFileInfo->fileSize > 0 && pFileInfo->firstVer >= 0 && pFileInfo->lastVer >= pFileInfo->firstVer);
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
  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) {
548
      wError("vgId:%d, failed to seek file due to %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId, strerror(errno),
549
             offset, fnameStr);
L
Liu Jicong 已提交
550
      terrno = TAOS_SYSTEM_ERROR(errno);
551 552 553 554 555 556 557 558
      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 已提交
559 560
    }

561
    if (idxEntry.ver > pFileInfo->lastVer) {
L
Liu Jicong 已提交
562 563
      continue;
    }
L
Liu Jicong 已提交
564

565 566 567 568
    if (offset != (idxEntry.ver - pFileInfo->firstVer) * sizeof(SWalIdxEntry)) {
      continue;
    }

569 570 571 572
    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 已提交
573 574
    }

575 576
    if (idxEntry.ver == ckHead.head.version) {
      break;
L
Liu Jicong 已提交
577
    }
578 579
  }
  offset += sizeof(SWalIdxEntry);
L
Liu Jicong 已提交
580

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

583 584 585 586 587 588 589 590 591 592 593 594
  // 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) {
595
    wError("vgId:%d, failed to seek file due to %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId, strerror(errno),
596 597 598 599 600
           offset, fnameStr);
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

601
  int64_t count = 0;
602
  while (idxEntry.ver < pFileInfo->lastVer) {
603
    ASSERT(idxEntry.ver == ckHead.head.version);
604 605 606 607 608 609 610 611 612 613 614 615 616

    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;
    }
    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;
    }
617
    count++;
618 619 620 621 622 623 624
  }

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

625 626 627 628 629
  if (count > 0) {
    wInfo("vgId:%d, rebuilt %" PRId64 " wal idx entries until lastVer: %" PRId64, pWal->cfg.vgId, count,
          pFileInfo->lastVer);
  }

630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
  (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 已提交
647 648
    }
  }
L
Liu Jicong 已提交
649 650 651
  return 0;
}

L
Liu Jicong 已提交
652 653 654 655
int walRollFileInfo(SWal* pWal) {
  int64_t ts = taosGetTimestampSec();

  SArray* pArray = pWal->fileInfoSet;
L
Liu Jicong 已提交
656
  if (taosArrayGetSize(pArray) != 0) {
L
Liu Jicong 已提交
657
    SWalFileInfo* pInfo = taosArrayGetLast(pArray);
L
Liu Jicong 已提交
658
    pInfo->lastVer = pWal->vers.lastVer;
L
Liu Jicong 已提交
659 660 661
    pInfo->closeTs = ts;
  }

L
Liu Jicong 已提交
662
  // TODO: change to emplace back
wafwerar's avatar
wafwerar 已提交
663
  SWalFileInfo* pNewInfo = taosMemoryMalloc(sizeof(SWalFileInfo));
L
Liu Jicong 已提交
664
  if (pNewInfo == NULL) {
S
Shengliang Guan 已提交
665
    terrno = TSDB_CODE_OUT_OF_MEMORY;
L
Liu Jicong 已提交
666 667
    return -1;
  }
L
Liu Jicong 已提交
668
  pNewInfo->firstVer = pWal->vers.lastVer + 1;
L
Liu Jicong 已提交
669 670 671 672
  pNewInfo->lastVer = -1;
  pNewInfo->createTs = ts;
  pNewInfo->closeTs = -1;
  pNewInfo->fileSize = 0;
673
  pNewInfo->syncedOffset = 0;
L
Liu Jicong 已提交
674
  taosArrayPush(pArray, pNewInfo);
wafwerar's avatar
wafwerar 已提交
675
  taosMemoryFree(pNewInfo);
L
Liu Jicong 已提交
676 677 678
  return 0;
}

679
char* walMetaSerialize(SWal* pWal) {
L
Liu Jicong 已提交
680
  char buf[30];
681
  ASSERT(pWal->fileInfoSet);
L
Liu Jicong 已提交
682
  int    sz = taosArrayGetSize(pWal->fileInfoSet);
683 684 685 686
  cJSON* pRoot = cJSON_CreateObject();
  cJSON* pMeta = cJSON_CreateObject();
  cJSON* pFiles = cJSON_CreateArray();
  cJSON* pField;
L
Liu Jicong 已提交
687
  if (pRoot == NULL || pMeta == NULL || pFiles == NULL) {
L
Liu Jicong 已提交
688
    if (pRoot) {
L
Liu Jicong 已提交
689 690
      cJSON_Delete(pRoot);
    }
L
Liu Jicong 已提交
691
    if (pMeta) {
L
Liu Jicong 已提交
692 693
      cJSON_Delete(pMeta);
    }
L
Liu Jicong 已提交
694
    if (pFiles) {
L
Liu Jicong 已提交
695 696
      cJSON_Delete(pFiles);
    }
S
Shengliang Guan 已提交
697
    terrno = TSDB_CODE_OUT_OF_MEMORY;
L
Liu Jicong 已提交
698 699
    return NULL;
  }
700
  cJSON_AddItemToObject(pRoot, "meta", pMeta);
L
Liu Jicong 已提交
701
  sprintf(buf, "%" PRId64, pWal->vers.firstVer);
702
  cJSON_AddStringToObject(pMeta, "firstVer", buf);
L
Liu Jicong 已提交
703
  sprintf(buf, "%" PRId64, pWal->vers.snapshotVer);
704
  cJSON_AddStringToObject(pMeta, "snapshotVer", buf);
L
Liu Jicong 已提交
705
  sprintf(buf, "%" PRId64, pWal->vers.commitVer);
706
  cJSON_AddStringToObject(pMeta, "commitVer", buf);
L
Liu Jicong 已提交
707
  sprintf(buf, "%" PRId64, pWal->vers.lastVer);
708 709 710
  cJSON_AddStringToObject(pMeta, "lastVer", buf);

  cJSON_AddItemToObject(pRoot, "files", pFiles);
L
Liu Jicong 已提交
711
  SWalFileInfo* pData = pWal->fileInfoSet->pData;
L
Liu Jicong 已提交
712
  for (int i = 0; i < sz; i++) {
L
Liu Jicong 已提交
713
    SWalFileInfo* pInfo = &pData[i];
714
    cJSON_AddItemToArray(pFiles, pField = cJSON_CreateObject());
L
Liu Jicong 已提交
715
    if (pField == NULL) {
716
      cJSON_Delete(pRoot);
L
Liu Jicong 已提交
717 718
      return NULL;
    }
L
Liu Jicong 已提交
719 720
    // cjson only support int32_t or double
    // string are used to prohibit the loss of precision
721 722 723 724 725 726 727 728 729 730
    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 已提交
731
  }
L
Liu Jicong 已提交
732 733 734
  char* serialized = cJSON_Print(pRoot);
  cJSON_Delete(pRoot);
  return serialized;
L
Liu Jicong 已提交
735 736
}

737
int walMetaDeserialize(SWal* pWal, const char* bytes) {
738
  ASSERT(taosArrayGetSize(pWal->fileInfoSet) == 0);
739 740
  cJSON *pRoot, *pMeta, *pFiles, *pInfoJson, *pField;
  pRoot = cJSON_Parse(bytes);
741
  if (!pRoot) goto _err;
742
  pMeta = cJSON_GetObjectItem(pRoot, "meta");
743
  if (!pMeta) goto _err;
744
  pField = cJSON_GetObjectItem(pMeta, "firstVer");
745
  if (!pField) goto _err;
L
Liu Jicong 已提交
746
  pWal->vers.firstVer = atoll(cJSON_GetStringValue(pField));
747
  pField = cJSON_GetObjectItem(pMeta, "snapshotVer");
748
  if (!pField) goto _err;
L
Liu Jicong 已提交
749
  pWal->vers.snapshotVer = atoll(cJSON_GetStringValue(pField));
750
  pField = cJSON_GetObjectItem(pMeta, "commitVer");
751
  if (!pField) goto _err;
L
Liu Jicong 已提交
752
  pWal->vers.commitVer = atoll(cJSON_GetStringValue(pField));
753
  pField = cJSON_GetObjectItem(pMeta, "lastVer");
754
  if (!pField) goto _err;
L
Liu Jicong 已提交
755
  pWal->vers.lastVer = atoll(cJSON_GetStringValue(pField));
756 757 758

  pFiles = cJSON_GetObjectItem(pRoot, "files");
  int sz = cJSON_GetArraySize(pFiles);
L
Liu Jicong 已提交
759
  // deserialize
L
Liu Jicong 已提交
760 761
  SArray* pArray = pWal->fileInfoSet;
  taosArrayEnsureCap(pArray, sz);
762

L
Liu Jicong 已提交
763
  for (int i = 0; i < sz; i++) {
764
    pInfoJson = cJSON_GetArrayItem(pFiles, i);
765
    if (!pInfoJson) goto _err;
766 767 768

    SWalFileInfo info = {0};

L
Liu Jicong 已提交
769
    pField = cJSON_GetObjectItem(pInfoJson, "firstVer");
770
    if (!pField) goto _err;
771
    info.firstVer = atoll(cJSON_GetStringValue(pField));
L
Liu Jicong 已提交
772
    pField = cJSON_GetObjectItem(pInfoJson, "lastVer");
773
    if (!pField) goto _err;
774
    info.lastVer = atoll(cJSON_GetStringValue(pField));
L
Liu Jicong 已提交
775
    pField = cJSON_GetObjectItem(pInfoJson, "createTs");
776
    if (!pField) goto _err;
777
    info.createTs = atoll(cJSON_GetStringValue(pField));
L
Liu Jicong 已提交
778
    pField = cJSON_GetObjectItem(pInfoJson, "closeTs");
779
    if (!pField) goto _err;
780
    info.closeTs = atoll(cJSON_GetStringValue(pField));
L
Liu Jicong 已提交
781
    pField = cJSON_GetObjectItem(pInfoJson, "fileSize");
782
    if (!pField) goto _err;
783 784
    info.fileSize = atoll(cJSON_GetStringValue(pField));
    taosArrayPush(pArray, &info);
L
Liu Jicong 已提交
785
  }
786
  pWal->fileInfoSet = pArray;
L
Liu Jicong 已提交
787
  pWal->writeCur = sz - 1;
L
Liu Jicong 已提交
788
  cJSON_Delete(pRoot);
789
  return 0;
790 791 792 793

_err:
  cJSON_Delete(pRoot);
  return -1;
L
Liu Jicong 已提交
794 795 796
}

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

wafwerar's avatar
wafwerar 已提交
801 802
  TdDirPtr pDir = taosOpenDir(pWal->path);
  if (pDir == NULL) {
L
Liu Jicong 已提交
803
    wError("vgId:%d, path:%s, failed to open since %s", pWal->cfg.vgId, pWal->path, strerror(errno));
L
Liu Jicong 已提交
804 805 806
    return -1;
  }

wafwerar's avatar
wafwerar 已提交
807
  TdDirEntryPtr pDirEntry;
L
Liu Jicong 已提交
808

L
Liu Jicong 已提交
809
  // find existing meta-ver[x].json
L
Liu Jicong 已提交
810
  int metaVer = -1;
wafwerar's avatar
wafwerar 已提交
811 812
  while ((pDirEntry = taosReadDir(pDir)) != NULL) {
    char* name = taosDirEntryBaseName(taosGetDirEntryName(pDirEntry));
L
Liu Jicong 已提交
813 814
    int   code = regexec(&walMetaRegexPattern, name, 0, NULL, 0);
    if (code == 0) {
L
Liu Jicong 已提交
815
      sscanf(name, "meta-ver%d", &metaVer);
L
Liu Jicong 已提交
816
      wDebug("vgId:%d, wal find current meta: %s is the meta file, ver %d", pWal->cfg.vgId, name, metaVer);
L
Liu Jicong 已提交
817 818
      break;
    }
L
Liu Jicong 已提交
819
    wDebug("vgId:%d, wal find current meta: %s is not meta file", pWal->cfg.vgId, name);
L
Liu Jicong 已提交
820
  }
wafwerar's avatar
wafwerar 已提交
821
  taosCloseDir(&pDir);
L
Liu Jicong 已提交
822
  regfree(&walMetaRegexPattern);
L
Liu Jicong 已提交
823 824 825
  return metaVer;
}

826 827 828 829 830 831
void walUpdateSyncedOffset(SWal* pWal) {
  SWalFileInfo* pFileInfo = walGetCurFileInfo(pWal);
  if (pFileInfo == NULL) return;
  pFileInfo->syncedOffset = pFileInfo->fileSize;
}

L
Liu Jicong 已提交
832
int walSaveMeta(SWal* pWal) {
L
Liu Jicong 已提交
833
  int  metaVer = walFindCurMetaVer(pWal);
L
Liu Jicong 已提交
834
  char fnameStr[WAL_FILE_LEN];
835
  char tmpFnameStr[WAL_FILE_LEN];
836 837 838 839 840 841 842 843 844 845 846 847 848 849
  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;
  }
850

851 852 853
  // update synced offset
  (void)walUpdateSyncedOffset(pWal);

854 855
  // flush to a tmpfile
  n = walBuildTmpMetaName(pWal, tmpFnameStr);
856
  ASSERT(n < sizeof(tmpFnameStr) && "Buffer overflow of file name");
857 858

  TdFilePtr pMetaFile = taosOpenFile(tmpFnameStr, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
L
Liu Jicong 已提交
859
  if (pMetaFile == NULL) {
860
    wError("vgId:%d, failed to open file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
861
    terrno = TAOS_SYSTEM_ERROR(errno);
L
Liu Jicong 已提交
862 863
    return -1;
  }
864

865
  char* serialized = walMetaSerialize(pWal);
L
Liu Jicong 已提交
866
  int   len = strlen(serialized);
L
Liu Jicong 已提交
867
  if (len != taosWriteFile(pMetaFile, serialized, len)) {
868
    wError("vgId:%d, failed to write file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
869 870 871
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }
L
Liu Jicong 已提交
872

873
  if (taosFsyncFile(pMetaFile) < 0) {
874
    wError("vgId:%d, failed to sync file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
875 876 877 878 879
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

  if (taosCloseFile(&pMetaFile) < 0) {
880
    wError("vgId:%d, failed to close file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
881 882 883 884 885 886
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

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

  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 已提交
893
  }
L
Liu Jicong 已提交
894 895 896

  // delete old file
  if (metaVer > -1) {
L
Liu Jicong 已提交
897
    walBuildMetaName(pWal, metaVer, fnameStr);
898
    taosRemoveFile(fnameStr);
L
Liu Jicong 已提交
899
  }
wafwerar's avatar
wafwerar 已提交
900
  taosMemoryFree(serialized);
L
Liu Jicong 已提交
901
  return 0;
902 903 904 905 906

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

L
Liu Jicong 已提交
909
int walLoadMeta(SWal* pWal) {
910
  ASSERT(pWal->fileInfoSet->size == 0);
L
Liu Jicong 已提交
911
  // find existing meta file
L
Liu Jicong 已提交
912
  int metaVer = walFindCurMetaVer(pWal);
L
Liu Jicong 已提交
913
  if (metaVer == -1) {
S
Shengliang Guan 已提交
914
    wDebug("vgId:%d, wal find meta ver %d", pWal->cfg.vgId, metaVer);
L
Liu Jicong 已提交
915
    return -1;
L
Liu Jicong 已提交
916 917 918
  }
  char fnameStr[WAL_FILE_LEN];
  walBuildMetaName(pWal, metaVer, fnameStr);
L
Liu Jicong 已提交
919
  // read metafile
L
Liu Jicong 已提交
920 921
  int64_t fileSize = 0;
  taosStatFile(fnameStr, &fileSize, NULL);
L
Liu Jicong 已提交
922 923
  if (fileSize == 0) {
    taosRemoveFile(fnameStr);
S
Shengliang Guan 已提交
924
    wDebug("vgId:%d, wal find empty meta ver %d", pWal->cfg.vgId, metaVer);
L
Liu Jicong 已提交
925 926
    return -1;
  }
L
Liu Jicong 已提交
927
  int   size = (int)fileSize;
wafwerar's avatar
wafwerar 已提交
928
  char* buf = taosMemoryMalloc(size + 5);
L
Liu Jicong 已提交
929
  if (buf == NULL) {
S
Shengliang Guan 已提交
930
    terrno = TSDB_CODE_OUT_OF_MEMORY;
L
Liu Jicong 已提交
931 932
    return -1;
  }
L
Liu Jicong 已提交
933
  memset(buf, 0, size + 5);
934 935
  TdFilePtr pFile = taosOpenFile(fnameStr, TD_FILE_READ);
  if (pFile == NULL) {
L
Liu Jicong 已提交
936
    terrno = TSDB_CODE_WAL_FILE_CORRUPTED;
L
Liu Jicong 已提交
937
    taosMemoryFree(buf);
L
Liu Jicong 已提交
938 939
    return -1;
  }
940
  if (taosReadFile(pFile, buf, size) != size) {
L
Liu Jicong 已提交
941
    terrno = TAOS_SYSTEM_ERROR(errno);
942
    taosCloseFile(&pFile);
wafwerar's avatar
wafwerar 已提交
943
    taosMemoryFree(buf);
L
Liu Jicong 已提交
944 945
    return -1;
  }
L
Liu Jicong 已提交
946
  // load into fileInfoSet
947
  int code = walMetaDeserialize(pWal, buf);
948 949 950 951
  if (code < 0) {
    wError("failed to deserialize wal meta. file:%s", fnameStr);
    terrno = TSDB_CODE_WAL_FILE_CORRUPTED;
  }
952
  taosCloseFile(&pFile);
wafwerar's avatar
wafwerar 已提交
953
  taosMemoryFree(buf);
L
Liu Jicong 已提交
954
  return code;
L
Liu Jicong 已提交
955
}
956 957 958 959 960 961

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