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

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

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

27
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
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;
}

325 326 327 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
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 已提交
354 355 356 357
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 已提交
358 359
  regex_t     logRegPattern;
  regex_t     idxRegPattern;
L
Liu Jicong 已提交
360 361 362

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

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

372 373
  SArray* actualLog = taosArrayInit(8, sizeof(SWalFileInfo));

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

wafwerar's avatar
wafwerar 已提交
387
  taosCloseDir(&pDir);
L
Liu Jicong 已提交
388 389 390
  regfree(&logRegPattern);
  regfree(&idxRegPattern);

391
  taosArraySort(actualLog, compareWalFileInfo);
L
Liu Jicong 已提交
392

393 394 395 396 397 398 399 400 401 402 403 404
  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 已提交
405

406 407 408 409
  // scan and determine the lastVer
  int32_t fileIdx = sz;

  while (--fileIdx >= 0) {
L
Liu Jicong 已提交
410
    char          fnameStr[WAL_FILE_LEN];
411 412 413
    int64_t       fileSize = 0;
    SWalFileInfo* pFileInfo = taosArrayGet(pWal->fileInfoSet, fileIdx);

L
Liu Jicong 已提交
414
    walBuildLogName(pWal, pFileInfo->firstVer, fnameStr);
415 416 417 418 419
    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 已提交
420 421
    }

422 423 424
    if (pFileInfo->lastVer >= pFileInfo->firstVer && fileSize == pFileInfo->fileSize) {
      totSize += pFileInfo->fileSize;
      continue;
L
Liu Jicong 已提交
425
    }
426
    updateMeta = true;
L
Liu Jicong 已提交
427

428 429
    (void)walTrimIdxFile(pWal, fileIdx);

430 431 432 433 434
    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 已提交
435
      }
436
      // remove the empty wal log, and its idx
437
      wInfo("vgId:%d, wal remove empty file %s", pWal->cfg.vgId, fnameStr);
438 439
      taosRemoveFile(fnameStr);
      walBuildIdxName(pWal, pFileInfo->firstVer, fnameStr);
440
      wInfo("vgId:%d, wal remove empty file %s", pWal->cfg.vgId, fnameStr);
441 442 443 444
      taosRemoveFile(fnameStr);
      // remove its meta entry
      taosArrayRemove(pWal->fileInfoSet, fileIdx);
      continue;
L
Liu Jicong 已提交
445 446
    }

447 448 449
    // update lastVer
    pFileInfo->lastVer = lastVer;
    totSize += pFileInfo->fileSize;
L
Liu Jicong 已提交
450
  }
L
Liu Jicong 已提交
451

452
  // reset vers info and so on
L
Liu Jicong 已提交
453
  actualFileNum = taosArrayGetSize(pWal->fileInfoSet);
L
Liu Jicong 已提交
454
  pWal->writeCur = actualFileNum - 1;
455 456
  pWal->totSize = totSize;
  pWal->vers.lastVer = -1;
L
Liu Jicong 已提交
457
  if (actualFileNum > 0) {
458 459
    pWal->vers.firstVer = ((SWalFileInfo*)taosArrayGet(pWal->fileInfoSet, 0))->firstVer;
    pWal->vers.lastVer = ((SWalFileInfo*)taosArrayGetLast(pWal->fileInfoSet))->lastVer;
L
Liu Jicong 已提交
460
  }
461
  (void)walAlignVersions(pWal);
L
Liu Jicong 已提交
462

463 464 465 466
  // update meta file
  if (updateMeta) {
    (void)walSaveMeta(pWal);
  }
467 468 469 470 471

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

472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
  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 已提交
489 490
  }

L
Liu Jicong 已提交
491 492 493
  return 0;
}

494
int walCheckAndRepairIdxFile(SWal* pWal, int32_t fileIdx) {
L
Liu Jicong 已提交
495
  int32_t       sz = taosArrayGetSize(pWal->fileInfoSet);
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
  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) {
539
      wError("vgId:%d, failed to seek file due to %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId, strerror(errno),
540
             offset, fnameStr);
L
Liu Jicong 已提交
541
      terrno = TAOS_SYSTEM_ERROR(errno);
542 543 544 545 546 547 548 549
      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 已提交
550 551
    }

552
    if (idxEntry.ver > pFileInfo->lastVer) {
L
Liu Jicong 已提交
553 554
      continue;
    }
L
Liu Jicong 已提交
555

556 557 558 559
    if (offset != (idxEntry.ver - pFileInfo->firstVer) * sizeof(SWalIdxEntry)) {
      continue;
    }

560 561 562 563
    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 已提交
564 565
    }

566 567
    if (idxEntry.ver == ckHead.head.version) {
      break;
L
Liu Jicong 已提交
568
    }
569 570
  }
  offset += sizeof(SWalIdxEntry);
L
Liu Jicong 已提交
571

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

574 575 576 577 578 579 580 581 582 583 584 585
  // 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) {
586
    wError("vgId:%d, failed to seek file due to %s. offset:%" PRId64 ", file:%s", pWal->cfg.vgId, strerror(errno),
587 588 589 590 591
           offset, fnameStr);
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

592
  int64_t count = 0;
593
  while (idxEntry.ver < pFileInfo->lastVer) {
L
Liu Jicong 已提交
594
    /*A(idxEntry.ver == ckHead.head.version);*/
595 596 597 598 599 600 601 602 603 604 605 606 607

    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;
    }
608
    count++;
609 610 611 612 613 614 615
  }

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

616 617 618 619 620
  if (count > 0) {
    wInfo("vgId:%d, rebuilt %" PRId64 " wal idx entries until lastVer: %" PRId64, pWal->cfg.vgId, count,
          pFileInfo->lastVer);
  }

621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
  (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 已提交
638 639
    }
  }
L
Liu Jicong 已提交
640 641 642
  return 0;
}

L
Liu Jicong 已提交
643 644 645 646
int walRollFileInfo(SWal* pWal) {
  int64_t ts = taosGetTimestampSec();

  SArray* pArray = pWal->fileInfoSet;
L
Liu Jicong 已提交
647
  if (taosArrayGetSize(pArray) != 0) {
L
Liu Jicong 已提交
648
    SWalFileInfo* pInfo = taosArrayGetLast(pArray);
L
Liu Jicong 已提交
649
    pInfo->lastVer = pWal->vers.lastVer;
L
Liu Jicong 已提交
650 651 652
    pInfo->closeTs = ts;
  }

L
Liu Jicong 已提交
653
  // TODO: change to emplace back
wafwerar's avatar
wafwerar 已提交
654
  SWalFileInfo* pNewInfo = taosMemoryMalloc(sizeof(SWalFileInfo));
L
Liu Jicong 已提交
655
  if (pNewInfo == NULL) {
S
Shengliang Guan 已提交
656
    terrno = TSDB_CODE_OUT_OF_MEMORY;
L
Liu Jicong 已提交
657 658
    return -1;
  }
L
Liu Jicong 已提交
659
  pNewInfo->firstVer = pWal->vers.lastVer + 1;
L
Liu Jicong 已提交
660 661 662 663
  pNewInfo->lastVer = -1;
  pNewInfo->createTs = ts;
  pNewInfo->closeTs = -1;
  pNewInfo->fileSize = 0;
664
  pNewInfo->syncedOffset = 0;
L
Liu Jicong 已提交
665
  taosArrayPush(pArray, pNewInfo);
wafwerar's avatar
wafwerar 已提交
666
  taosMemoryFree(pNewInfo);
L
Liu Jicong 已提交
667 668 669
  return 0;
}

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

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

727
int walMetaDeserialize(SWal* pWal, const char* bytes) {
L
Liu Jicong 已提交
728
  /*A(taosArrayGetSize(pWal->fileInfoSet) == 0);*/
729 730
  cJSON *pRoot, *pMeta, *pFiles, *pInfoJson, *pField;
  pRoot = cJSON_Parse(bytes);
731
  if (!pRoot) goto _err;
732
  pMeta = cJSON_GetObjectItem(pRoot, "meta");
733
  if (!pMeta) goto _err;
734
  pField = cJSON_GetObjectItem(pMeta, "firstVer");
735
  if (!pField) goto _err;
L
Liu Jicong 已提交
736
  pWal->vers.firstVer = atoll(cJSON_GetStringValue(pField));
737
  pField = cJSON_GetObjectItem(pMeta, "snapshotVer");
738
  if (!pField) goto _err;
L
Liu Jicong 已提交
739
  pWal->vers.snapshotVer = atoll(cJSON_GetStringValue(pField));
740
  pField = cJSON_GetObjectItem(pMeta, "commitVer");
741
  if (!pField) goto _err;
L
Liu Jicong 已提交
742
  pWal->vers.commitVer = atoll(cJSON_GetStringValue(pField));
743
  pField = cJSON_GetObjectItem(pMeta, "lastVer");
744
  if (!pField) goto _err;
L
Liu Jicong 已提交
745
  pWal->vers.lastVer = atoll(cJSON_GetStringValue(pField));
746 747 748

  pFiles = cJSON_GetObjectItem(pRoot, "files");
  int sz = cJSON_GetArraySize(pFiles);
L
Liu Jicong 已提交
749
  // deserialize
L
Liu Jicong 已提交
750 751
  SArray* pArray = pWal->fileInfoSet;
  taosArrayEnsureCap(pArray, sz);
752

L
Liu Jicong 已提交
753
  for (int i = 0; i < sz; i++) {
754
    pInfoJson = cJSON_GetArrayItem(pFiles, i);
755
    if (!pInfoJson) goto _err;
756 757 758

    SWalFileInfo info = {0};

L
Liu Jicong 已提交
759
    pField = cJSON_GetObjectItem(pInfoJson, "firstVer");
760
    if (!pField) goto _err;
761
    info.firstVer = atoll(cJSON_GetStringValue(pField));
L
Liu Jicong 已提交
762
    pField = cJSON_GetObjectItem(pInfoJson, "lastVer");
763
    if (!pField) goto _err;
764
    info.lastVer = atoll(cJSON_GetStringValue(pField));
L
Liu Jicong 已提交
765
    pField = cJSON_GetObjectItem(pInfoJson, "createTs");
766
    if (!pField) goto _err;
767
    info.createTs = atoll(cJSON_GetStringValue(pField));
L
Liu Jicong 已提交
768
    pField = cJSON_GetObjectItem(pInfoJson, "closeTs");
769
    if (!pField) goto _err;
770
    info.closeTs = atoll(cJSON_GetStringValue(pField));
L
Liu Jicong 已提交
771
    pField = cJSON_GetObjectItem(pInfoJson, "fileSize");
772
    if (!pField) goto _err;
773 774
    info.fileSize = atoll(cJSON_GetStringValue(pField));
    taosArrayPush(pArray, &info);
L
Liu Jicong 已提交
775
  }
776
  pWal->fileInfoSet = pArray;
L
Liu Jicong 已提交
777
  pWal->writeCur = sz - 1;
L
Liu Jicong 已提交
778
  cJSON_Delete(pRoot);
779
  return 0;
780 781 782 783

_err:
  cJSON_Delete(pRoot);
  return -1;
L
Liu Jicong 已提交
784 785 786
}

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

wafwerar's avatar
wafwerar 已提交
791 792
  TdDirPtr pDir = taosOpenDir(pWal->path);
  if (pDir == NULL) {
L
Liu Jicong 已提交
793
    wError("vgId:%d, path:%s, failed to open since %s", pWal->cfg.vgId, pWal->path, strerror(errno));
L
Liu Jicong 已提交
794 795 796
    return -1;
  }

wafwerar's avatar
wafwerar 已提交
797
  TdDirEntryPtr pDirEntry;
L
Liu Jicong 已提交
798

L
Liu Jicong 已提交
799
  // find existing meta-ver[x].json
L
Liu Jicong 已提交
800
  int metaVer = -1;
wafwerar's avatar
wafwerar 已提交
801 802
  while ((pDirEntry = taosReadDir(pDir)) != NULL) {
    char* name = taosDirEntryBaseName(taosGetDirEntryName(pDirEntry));
L
Liu Jicong 已提交
803 804
    int   code = regexec(&walMetaRegexPattern, name, 0, NULL, 0);
    if (code == 0) {
L
Liu Jicong 已提交
805
      sscanf(name, "meta-ver%d", &metaVer);
L
Liu Jicong 已提交
806
      wDebug("vgId:%d, wal find current meta: %s is the meta file, ver %d", pWal->cfg.vgId, name, metaVer);
L
Liu Jicong 已提交
807 808
      break;
    }
L
Liu Jicong 已提交
809
    wDebug("vgId:%d, wal find current meta: %s is not meta file", pWal->cfg.vgId, name);
L
Liu Jicong 已提交
810
  }
wafwerar's avatar
wafwerar 已提交
811
  taosCloseDir(&pDir);
L
Liu Jicong 已提交
812
  regfree(&walMetaRegexPattern);
L
Liu Jicong 已提交
813 814 815
  return metaVer;
}

816 817 818 819 820 821
void walUpdateSyncedOffset(SWal* pWal) {
  SWalFileInfo* pFileInfo = walGetCurFileInfo(pWal);
  if (pFileInfo == NULL) return;
  pFileInfo->syncedOffset = pFileInfo->fileSize;
}

L
Liu Jicong 已提交
822
int walSaveMeta(SWal* pWal) {
L
Liu Jicong 已提交
823
  int  metaVer = walFindCurMetaVer(pWal);
L
Liu Jicong 已提交
824
  char fnameStr[WAL_FILE_LEN];
825
  char tmpFnameStr[WAL_FILE_LEN];
826 827 828 829 830 831 832 833 834 835 836 837 838 839
  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;
  }
840

841 842 843
  // update synced offset
  (void)walUpdateSyncedOffset(pWal);

844 845
  // flush to a tmpfile
  n = walBuildTmpMetaName(pWal, tmpFnameStr);
L
Liu Jicong 已提交
846
  if (n >= sizeof(tmpFnameStr)) {
L
Liu Jicong 已提交
847 848
    return -1;
  }
849 850

  TdFilePtr pMetaFile = taosOpenFile(tmpFnameStr, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
L
Liu Jicong 已提交
851
  if (pMetaFile == NULL) {
852
    wError("vgId:%d, failed to open file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
853
    terrno = TAOS_SYSTEM_ERROR(errno);
L
Liu Jicong 已提交
854 855
    return -1;
  }
856

857
  char* serialized = walMetaSerialize(pWal);
L
Liu Jicong 已提交
858
  int   len = strlen(serialized);
L
Liu Jicong 已提交
859
  if (len != taosWriteFile(pMetaFile, serialized, len)) {
860
    wError("vgId:%d, failed to write file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
861 862 863
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }
L
Liu Jicong 已提交
864

865
  if (taosFsyncFile(pMetaFile) < 0) {
866
    wError("vgId:%d, failed to sync file due to %s. file:%s", pWal->cfg.vgId, strerror(errno), tmpFnameStr);
867 868 869 870 871
    terrno = TAOS_SYSTEM_ERROR(errno);
    goto _err;
  }

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

  // rename it
  n = walBuildMetaName(pWal, metaVer + 1, fnameStr);
L
Liu Jicong 已提交
879
  if (n >= sizeof(fnameStr)) {
L
Liu Jicong 已提交
880 881
    goto _err;
  }
882 883 884 885 886

  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 已提交
887
  }
L
Liu Jicong 已提交
888 889 890

  // delete old file
  if (metaVer > -1) {
L
Liu Jicong 已提交
891
    walBuildMetaName(pWal, metaVer, fnameStr);
892
    taosRemoveFile(fnameStr);
L
Liu Jicong 已提交
893
  }
wafwerar's avatar
wafwerar 已提交
894
  taosMemoryFree(serialized);
L
Liu Jicong 已提交
895
  return 0;
896 897 898 899 900

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

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

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