tdbPager.c 12.7 KB
Newer Older
H
Hongze Cheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * 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/>.
H
refact  
Hongze Cheng 已提交
14 15
 */

H
Hongze Cheng 已提交
16 17
#include "tdbInt.h"

H
Hongze Cheng 已提交
18
#pragma pack(push, 1)
wafwerar's avatar
wafwerar 已提交
19
typedef struct {
H
Hongze Cheng 已提交
20 21 22 23 24
  u8    hdrString[16];
  u16   pageSize;
  SPgno freePage;
  u32   nFreePages;
  u8    reserved[102];
H
Hongze Cheng 已提交
25
} SFileHdr;
wafwerar's avatar
wafwerar 已提交
26
#pragma pack(pop)
H
Hongze Cheng 已提交
27

H
Hongze Cheng 已提交
28 29
TDB_STATIC_ASSERT(sizeof(SFileHdr) == 128, "Size of file header is not correct");

H
Hongze Cheng 已提交
30 31
#define TDB_PAGE_INITIALIZED(pPage) ((pPage)->pPager != NULL)

H
Hongze Cheng 已提交
32 33
static int tdbPagerInitPage(SPager *pPager, SPage *pPage, int (*initPage)(SPage *, void *, int), void *arg,
                            u8 loadPage);
H
Hongze Cheng 已提交
34 35
static int tdbPagerWritePageToJournal(SPager *pPager, SPage *pPage);
static int tdbPagerWritePageToDB(SPager *pPager, SPage *pPage);
H
Hongze Cheng 已提交
36

H
refact  
Hongze Cheng 已提交
37
int tdbPagerOpen(SPCache *pCache, const char *fileName, SPager **ppPager) {
H
more  
Hongze Cheng 已提交
38
  uint8_t *pPtr;
H
Hongze Cheng 已提交
39
  SPager  *pPager;
H
more  
Hongze Cheng 已提交
40 41
  int      fsize;
  int      zsize;
H
Hongze Cheng 已提交
42
  int      ret;
H
more  
Hongze Cheng 已提交
43

H
refact  
Hongze Cheng 已提交
44
  *ppPager = NULL;
H
more  
Hongze Cheng 已提交
45 46

  fsize = strlen(fileName);
H
refact  
Hongze Cheng 已提交
47
  zsize = sizeof(*pPager)  /* SPager */
H
more  
Hongze Cheng 已提交
48 49
          + fsize + 1      /* dbFileName */
          + fsize + 8 + 1; /* jFileName */
H
Hongze Cheng 已提交
50
  pPtr = (uint8_t *)tdbOsCalloc(1, zsize);
H
more  
Hongze Cheng 已提交
51 52 53 54
  if (pPtr == NULL) {
    return -1;
  }

H
refact  
Hongze Cheng 已提交
55 56 57 58 59 60
  pPager = (SPager *)pPtr;
  pPtr += sizeof(*pPager);
  // pPager->dbFileName
  pPager->dbFileName = (char *)pPtr;
  memcpy(pPager->dbFileName, fileName, fsize);
  pPager->dbFileName[fsize] = '\0';
H
more  
Hongze Cheng 已提交
61
  pPtr += fsize + 1;
H
refact  
Hongze Cheng 已提交
62 63 64 65 66 67 68 69
  // pPager->jFileName
  pPager->jFileName = (char *)pPtr;
  memcpy(pPager->jFileName, fileName, fsize);
  memcpy(pPager->jFileName + fsize, "-journal", 8);
  pPager->jFileName[fsize + 8] = '\0';
  // pPager->pCache
  pPager->pCache = pCache;

H
Hongze Cheng 已提交
70
  pPager->fd = tdbOsOpen(pPager->dbFileName, TDB_O_CREAT | TDB_O_RDWR, 0755);
H
refact  
Hongze Cheng 已提交
71
  if (pPager->fd < 0) {
H
more  
Hongze Cheng 已提交
72 73 74
    return -1;
  }

wafwerar's avatar
wafwerar 已提交
75
  ret = tdbGnrtFileID(pPager->fd, pPager->fid, false);
H
Hongze Cheng 已提交
76 77 78 79
  if (ret < 0) {
    return -1;
  }

H
Hongze Cheng 已提交
80
  // pPager->jfd = -1;
H
Hongze Cheng 已提交
81
  pPager->pageSize = tdbPCacheGetPageSize(pCache);
H
Hongze Cheng 已提交
82 83
  // pPager->dbOrigSize
  ret = tdbGetFileSize(pPager->fd, pPager->pageSize, &(pPager->dbOrigSize));
H
Hongze Cheng 已提交
84
  pPager->dbFileSize = pPager->dbOrigSize;
H
more  
Hongze Cheng 已提交
85

H
refact  
Hongze Cheng 已提交
86
  *ppPager = pPager;
H
more  
Hongze Cheng 已提交
87 88 89
  return 0;
}

H
refact  
Hongze Cheng 已提交
90
int tdbPagerClose(SPager *pPager) {
H
Hongze Cheng 已提交
91 92 93 94 95 96 97
  if (pPager) {
    if (pPager->inTran) {
      tdbOsClose(pPager->jfd);
    }
    tdbOsClose(pPager->fd);
    tdbOsFree(pPager);
  }
H
more  
Hongze Cheng 已提交
98 99 100
  return 0;
}

101
int tdbPagerOpenDB(SPager *pPager, SPgno *ppgno, bool toCreate, SBTree *pBt) {
H
Hongze Cheng 已提交
102 103 104 105
  SPgno  pgno;
  SPage *pPage;
  int    ret;

H
Hongze Cheng 已提交
106 107 108
  if (pPager->dbOrigSize > 0) {
    pgno = 1;
  } else {
H
Hongze Cheng 已提交
109 110 111
    pgno = 0;
  }

H
Hongze Cheng 已提交
112
  {
113 114
    // TODO: try to search the main DB to get the page number
    // pgno = 0;
H
Hongze Cheng 已提交
115 116
  }

117 118 119 120
  if (pgno == 0 && toCreate) {
    // allocate a new child page
    TXN txn;
    tdbTxnOpen(&txn, 0, tdbDefaultMalloc, tdbDefaultFree, NULL, 0);
H
Hongze Cheng 已提交
121

122
    pPager->inTran = 1;
H
refact  
Hongze Cheng 已提交
123

124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
    SBtreeInitPageArg zArg;
    zArg.flags = 0x1 | 0x2;  // root leaf node;
    zArg.pBt = pBt;
    ret = tdbPagerFetchPage(pPager, &pgno, &pPage, tdbBtreeInitPage, &zArg, &txn);
    if (ret < 0) {
      return -1;
    }

    //    ret = tdbPagerAllocPage(pPager, &pPage, &pgno);
    // if (ret < 0) {
    //  return -1;
    //}

    // TODO: Need to zero the page

    ret = tdbPagerWrite(pPager, pPage);
    if (ret < 0) {
      return -1;
    }
H
Hongze Cheng 已提交
143

144 145 146 147
    tdbTxnClose(&txn);
  }

  *ppgno = pgno;
H
Hongze Cheng 已提交
148 149 150
  return 0;
}

H
refact  
Hongze Cheng 已提交
151
int tdbPagerWrite(SPager *pPager, SPage *pPage) {
H
Hongze Cheng 已提交
152 153
  int     ret;
  SPage **ppPage;
H
more  
Hongze Cheng 已提交
154

H
Hongze Cheng 已提交
155 156
  ASSERT(pPager->inTran);
#if 0
H
refact  
Hongze Cheng 已提交
157 158
  if (pPager->inTran == 0) {
    ret = tdbPagerBegin(pPager);
H
more  
Hongze Cheng 已提交
159 160 161 162
    if (ret < 0) {
      return -1;
    }
  }
H
Hongze Cheng 已提交
163
#endif
H
more  
Hongze Cheng 已提交
164

H
Hongze Cheng 已提交
165
  if (pPage->isDirty) return 0;
H
more  
Hongze Cheng 已提交
166

H
Hongze Cheng 已提交
167
  // ref page one more time so the page will not be release
H
Hongze Cheng 已提交
168
  tdbRefPage(pPage);
M
Minglei Jin 已提交
169
  tdbDebug("pcache/mdirty page %p/%d/%d", pPage, TDB_PAGE_PGNO(pPage), pPage->id);
H
Hongze Cheng 已提交
170

H
Hongze Cheng 已提交
171 172 173
  // Set page as dirty
  pPage->isDirty = 1;

H
Hongze Cheng 已提交
174
  // Add page to dirty list(TODO: NOT use O(n^2) algorithm)
H
Hongze Cheng 已提交
175 176 177
  for (ppPage = &pPager->pDirty; (*ppPage) && TDB_PAGE_PGNO(*ppPage) < TDB_PAGE_PGNO(pPage);
       ppPage = &((*ppPage)->pDirtyNext)) {
  }
178 179 180 181 182 183 184

  if (*ppPage && TDB_PAGE_PGNO(*ppPage) == TDB_PAGE_PGNO(pPage)) {
    tdbUnrefPage(pPage);

    return 0;
  }

H
Hongze Cheng 已提交
185 186 187
  ASSERT(*ppPage == NULL || TDB_PAGE_PGNO(*ppPage) > TDB_PAGE_PGNO(pPage));
  pPage->pDirtyNext = *ppPage;
  *ppPage = pPage;
H
Hongze Cheng 已提交
188

H
Hongze Cheng 已提交
189
  // Write page to journal if neccessary
H
Hongze Cheng 已提交
190 191 192 193 194
  if (TDB_PAGE_PGNO(pPage) <= pPager->dbOrigSize) {
    ret = tdbPagerWritePageToJournal(pPager, pPage);
    if (ret < 0) {
      ASSERT(0);
      return -1;
H
Hongze Cheng 已提交
195
    }
H
more  
Hongze Cheng 已提交
196
  }
H
Hongze Cheng 已提交
197

H
Hongze Cheng 已提交
198 199 200
  return 0;
}

H
Hongze Cheng 已提交
201
int tdbPagerBegin(SPager *pPager, TXN *pTxn) {
H
refact  
Hongze Cheng 已提交
202
  if (pPager->inTran) {
H
more  
Hongze Cheng 已提交
203 204
    return 0;
  }
H
Hongze Cheng 已提交
205 206

  // Open the journal
H
Hongze Cheng 已提交
207
  pPager->jfd = tdbOsOpen(pPager->jFileName, TDB_O_CREAT | TDB_O_RDWR, 0755);
H
refact  
Hongze Cheng 已提交
208
  if (pPager->jfd < 0) {
H
Hongze Cheng 已提交
209 210 211 212 213
    return -1;
  }

  // TODO: write the size of the file

H
refact  
Hongze Cheng 已提交
214
  pPager->inTran = 1;
H
Hongze Cheng 已提交
215

H
more  
Hongze Cheng 已提交
216 217 218
  return 0;
}

H
Hongze Cheng 已提交
219
int tdbPagerCommit(SPager *pPager, TXN *pTxn) {
H
Hongze Cheng 已提交
220 221 222
  SPage *pPage;
  int    ret;

H
Hongze Cheng 已提交
223 224 225 226 227 228
  // sync the journal file
  ret = tdbOsFSync(pPager->jfd);
  if (ret < 0) {
    // TODO
    ASSERT(0);
    return 0;
H
Hongze Cheng 已提交
229 230
  }

H
Hongze Cheng 已提交
231 232
  // loop to write the dirty pages to file
  for (pPage = pPager->pDirty; pPage; pPage = pPage->pDirtyNext) {
H
Hongze Cheng 已提交
233
    // TODO: update the page footer
H
Hongze Cheng 已提交
234 235 236 237 238 239 240
    ret = tdbPagerWritePageToDB(pPager, pPage);
    if (ret < 0) {
      ASSERT(0);
      return -1;
    }
  }

241
  tdbTrace("tdbttl commit:%p, %d", pPager, pPager->dbOrigSize);
H
Hongze Cheng 已提交
242 243
  pPager->dbOrigSize = pPager->dbFileSize;

H
Hongze Cheng 已提交
244
  // release the page
H
Hongze Cheng 已提交
245
  for (pPage = pPager->pDirty; pPage; pPage = pPager->pDirty) {
H
Hongze Cheng 已提交
246 247 248 249 250
    pPager->pDirty = pPage->pDirtyNext;
    pPage->pDirtyNext = NULL;

    pPage->isDirty = 0;

H
Hongze Cheng 已提交
251
    tdbPCacheRelease(pPager->pCache, pPage, pTxn);
H
Hongze Cheng 已提交
252
  }
H
Hongze Cheng 已提交
253 254

  // sync the db file
H
Hongze Cheng 已提交
255
  tdbOsFSync(pPager->fd);
H
Hongze Cheng 已提交
256

257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 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
  // remove the journal file
  tdbOsClose(pPager->jfd);
  tdbOsRemove(pPager->jFileName);
  pPager->inTran = 0;

  return 0;
}

// recovery dirty pages
int tdbPagerAbort(SPager *pPager, TXN *pTxn) {
  SPage *pPage;
  int    pgIdx;
  SPgno  journalSize = 0;
  int    ret;

  // 0, sync the journal file
  ret = tdbOsFSync(pPager->jfd);
  if (ret < 0) {
    // TODO
    ASSERT(0);
    return 0;
  }

  tdb_fd_t jfd = tdbOsOpen(pPager->jFileName, TDB_O_RDWR, 0755);
  if (jfd == NULL) {
    return 0;
  }

  ret = tdbGetFileSize(jfd, pPager->pageSize, &journalSize);
  if (ret < 0) {
    return -1;
  }

  // 1, read pages from jounal file
  // 2, write original pages to buffered ones

  /* TODO: reset the buffered pages instead of releasing them
  // loop to reset the dirty pages from file
  for (pgIdx = 0, pPage = pPager->pDirty; pPage != NULL && pgIndex < journalSize; pPage = pPage->pDirtyNext, ++pgIdx) {
    // read pgno & the page from journal
    SPgno pgno;

    int ret = tdbOsRead(jfd, &pgno, sizeof(pgno));
    if (ret < 0) {
      return -1;
    }

    ret = tdbOsRead(jfd, pageBuf, pPager->pageSize);
    if (ret < 0) {
      return -1;
    }
  }
  */
  // 3, release the dirty pages
  for (pPage = pPager->pDirty; pPage; pPage = pPager->pDirty) {
    pPager->pDirty = pPage->pDirtyNext;
    pPage->pDirtyNext = NULL;

    pPage->isDirty = 0;

    tdbPCacheRelease(pPager->pCache, pPage, pTxn);
  }

  // 4, remove the journal file
H
Hongze Cheng 已提交
321
  tdbOsClose(pPager->jfd);
H
Hongze Cheng 已提交
322
  tdbOsRemove(pPager->jFileName);
H
Hongze Cheng 已提交
323
  pPager->inTran = 0;
H
Hongze Cheng 已提交
324

H
more  
Hongze Cheng 已提交
325 326 327
  return 0;
}

H
Hongze Cheng 已提交
328
int tdbPagerFetchPage(SPager *pPager, SPgno *ppgno, SPage **ppPage, int (*initPage)(SPage *, void *, int), void *arg,
H
Hongze Cheng 已提交
329
                      TXN *pTxn) {
H
more  
Hongze Cheng 已提交
330 331 332
  SPage *pPage;
  SPgid  pgid;
  int    ret;
H
Hongze Cheng 已提交
333 334
  SPgno  pgno;
  u8     loadPage;
H
more  
Hongze Cheng 已提交
335

H
Hongze Cheng 已提交
336 337
  pgno = *ppgno;
  loadPage = 1;
H
more  
Hongze Cheng 已提交
338

H
Hongze Cheng 已提交
339 340 341 342
  // alloc new page
  if (pgno == 0) {
    loadPage = 0;
    ret = tdbPagerAllocPage(pPager, &pgno);
H
Hongze Cheng 已提交
343
    if (ret < 0) {
H
Hongze Cheng 已提交
344
      ASSERT(0);
H
Hongze Cheng 已提交
345
      return -1;
H
more  
Hongze Cheng 已提交
346
    }
H
more  
Hongze Cheng 已提交
347 348
  }

H
Hongze Cheng 已提交
349
  ASSERT(pgno > 0);
H
Hongze Cheng 已提交
350

H
Hongze Cheng 已提交
351
  // fetch a page container
H
more  
Hongze Cheng 已提交
352
  memcpy(&pgid, pPager->fid, TDB_FILE_ID_LEN);
H
Hongze Cheng 已提交
353
  pgid.pgno = pgno;
H
Hongze Cheng 已提交
354
  pPage = tdbPCacheFetch(pPager->pCache, &pgid, pTxn);
H
more  
Hongze Cheng 已提交
355
  if (pPage == NULL) {
H
Hongze Cheng 已提交
356
    ASSERT(0);
H
more  
Hongze Cheng 已提交
357 358 359
    return -1;
  }

360
  tdbTrace("tdbttl fetch pager:%p", pPage->pPager);
H
Hongze Cheng 已提交
361 362 363 364
  // init page if need
  if (!TDB_PAGE_INITIALIZED(pPage)) {
    ret = tdbPagerInitPage(pPager, pPage, initPage, arg, loadPage);
    if (ret < 0) {
H
Hongze Cheng 已提交
365
      ASSERT(0);
H
Hongze Cheng 已提交
366 367
      return -1;
    }
H
Hongze Cheng 已提交
368
  }
H
more  
Hongze Cheng 已提交
369

H
Hongze Cheng 已提交
370 371 372
  // printf("thread %" PRId64 " pager fetch page %d pgno %d ppage %p\n", taosGetSelfPthreadId(), pPage->id,
  //        TDB_PAGE_PGNO(pPage), pPage);

H
Hongze Cheng 已提交
373 374
  ASSERT(TDB_PAGE_INITIALIZED(pPage));
  ASSERT(pPage->pPager == pPager);
H
more  
Hongze Cheng 已提交
375

H
Hongze Cheng 已提交
376
  *ppgno = pgno;
H
more  
Hongze Cheng 已提交
377 378 379 380
  *ppPage = pPage;
  return 0;
}

H
Hongze Cheng 已提交
381 382 383 384 385
void tdbPagerReturnPage(SPager *pPager, SPage *pPage, TXN *pTxn) {
  tdbPCacheRelease(pPager->pCache, pPage, pTxn);
  // printf("thread %" PRId64 " pager retun page %d pgno %d ppage %p\n", taosGetSelfPthreadId(), pPage->id,
  //        TDB_PAGE_PGNO(pPage), pPage);
}
H
Hongze Cheng 已提交
386

H
more  
Hongze Cheng 已提交
387 388 389 390 391 392 393 394 395 396
static int tdbPagerAllocFreePage(SPager *pPager, SPgno *ppgno) {
  // TODO: Allocate a page from the free list
  return 0;
}

static int tdbPagerAllocNewPage(SPager *pPager, SPgno *ppgno) {
  *ppgno = ++pPager->dbFileSize;
  return 0;
}

H
Hongze Cheng 已提交
397
int tdbPagerAllocPage(SPager *pPager, SPgno *ppgno) {
H
more  
Hongze Cheng 已提交
398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
  int ret;

  *ppgno = 0;

  // Try to allocate from the free list of the pager
  ret = tdbPagerAllocFreePage(pPager, ppgno);
  if (ret < 0) {
    return -1;
  }

  if (*ppgno != 0) return 0;

  // Allocate the page by extending the pager
  ret = tdbPagerAllocNewPage(pPager, ppgno);
  if (ret < 0) {
    return -1;
  }

  ASSERT(*ppgno != 0);

H
Hongze Cheng 已提交
418 419 420
  return 0;
}

H
Hongze Cheng 已提交
421 422 423 424 425 426 427 428
static int tdbPagerInitPage(SPager *pPager, SPage *pPage, int (*initPage)(SPage *, void *, int), void *arg,
                            u8 loadPage) {
  int   ret;
  int   lcode;
  int   nLoops;
  i64   nRead;
  SPgno pgno;
  int   init = 0;
H
Hongze Cheng 已提交
429

H
Hongze Cheng 已提交
430 431
  lcode = TDB_TRY_LOCK_PAGE(pPage);
  if (lcode == P_LOCK_SUCC) {
H
Hongze Cheng 已提交
432 433 434 435 436
    if (TDB_PAGE_INITIALIZED(pPage)) {
      TDB_UNLOCK_PAGE(pPage);
      return 0;
    }

H
Hongze Cheng 已提交
437 438
    pgno = TDB_PAGE_PGNO(pPage);

439
    tdbTrace("tdbttl init pager:%p, pgno:%d, loadPage:%d, size:%d", pPager, pgno, loadPage, pPager->dbOrigSize);
H
Hongze Cheng 已提交
440 441 442
    if (loadPage && pgno <= pPager->dbOrigSize) {
      init = 1;

H
Hongze Cheng 已提交
443
      nRead = tdbOsPRead(pPager->fd, pPage->pData, pPage->pageSize, ((i64)pPage->pageSize) * (pgno - 1));
S
Shengliang Guan 已提交
444
      tdbTrace("tdbttl pager:%p, pgno:%d, nRead:%" PRId64, pPager, pgno, nRead);
H
Hongze Cheng 已提交
445
      if (nRead < pPage->pageSize) {
H
Hongze Cheng 已提交
446 447 448
        ASSERT(0);
        return -1;
      }
H
Hongze Cheng 已提交
449 450
    } else {
      init = 0;
H
Hongze Cheng 已提交
451 452
    }

H
Hongze Cheng 已提交
453
    ret = (*initPage)(pPage, arg, init);
H
Hongze Cheng 已提交
454
    if (ret < 0) {
H
Hongze Cheng 已提交
455
      ASSERT(0);
H
Hongze Cheng 已提交
456 457 458 459 460 461 462
      TDB_UNLOCK_PAGE(pPage);
      return -1;
    }

    pPage->pPager = pPager;

    TDB_UNLOCK_PAGE(pPage);
H
Hongze Cheng 已提交
463
  } else if (lcode == P_LOCK_BUSY) {
H
Hongze Cheng 已提交
464 465 466 467 468 469 470 471 472
    nLoops = 0;
    for (;;) {
      if (TDB_PAGE_INITIALIZED(pPage)) break;
      nLoops++;
      if (nLoops > 1000) {
        sched_yield();
        nLoops = 0;
      }
    }
H
Hongze Cheng 已提交
473
  } else {
H
Hongze Cheng 已提交
474
    ASSERT(0);
H
Hongze Cheng 已提交
475
    return -1;
H
Hongze Cheng 已提交
476 477
  }

H
Hongze Cheng 已提交
478 479 480 481 482 483 484 485 486 487
  return 0;
}

// ---------------------------- Journal manipulation
static int tdbPagerWritePageToJournal(SPager *pPager, SPage *pPage) {
  int   ret;
  SPgno pgno;

  pgno = TDB_PAGE_PGNO(pPage);

H
Hongze Cheng 已提交
488
  ret = tdbOsWrite(pPager->jfd, &pgno, sizeof(pgno));
H
Hongze Cheng 已提交
489 490 491 492
  if (ret < 0) {
    return -1;
  }

H
Hongze Cheng 已提交
493
  ret = tdbOsWrite(pPager->jfd, pPage->pData, pPage->pageSize);
H
Hongze Cheng 已提交
494 495 496 497 498 499 500 501 502 503 504
  if (ret < 0) {
    return -1;
  }

  return 0;
}

static int tdbPagerWritePageToDB(SPager *pPager, SPage *pPage) {
  i64 offset;
  int ret;

505
  offset = (i64)pPage->pageSize * (TDB_PAGE_PGNO(pPage) - 1);
H
Hongze Cheng 已提交
506
  if (tdbOsLSeek(pPager->fd, offset, SEEK_SET) < 0) {
H
Hongze Cheng 已提交
507 508 509 510
    ASSERT(0);
    return -1;
  }

H
Hongze Cheng 已提交
511
  ret = tdbOsWrite(pPager->fd, pPage->pData, pPage->pageSize);
H
Hongze Cheng 已提交
512 513 514 515 516
  if (ret < 0) {
    ASSERT(0);
    return -1;
  }

H
refact  
Hongze Cheng 已提交
517
  return 0;
518 519 520
}

int tdbPagerRestore(SPager *pPager, SBTree *pBt) {
521
  int   ret = 0;
522
  SPgno journalSize = 0;
523
  u8   *pageBuf = NULL;
524 525

  tdb_fd_t jfd = tdbOsOpen(pPager->jFileName, TDB_O_RDWR, 0755);
526
  if (jfd == NULL) {
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
    return 0;
  }

  ret = tdbGetFileSize(jfd, pPager->pageSize, &journalSize);
  if (ret < 0) {
    return -1;
  }

  pageBuf = tdbOsCalloc(1, pPager->pageSize);
  if (pageBuf == NULL) {
    return -1;
  }

  for (int pgIndex = 0; pgIndex < journalSize; ++pgIndex) {
    // read pgno & the page from journal
542
    SPgno pgno;
543 544 545 546 547 548 549 550 551 552 553

    int ret = tdbOsRead(jfd, &pgno, sizeof(pgno));
    if (ret < 0) {
      return -1;
    }

    ret = tdbOsRead(jfd, pageBuf, pPager->pageSize);
    if (ret < 0) {
      return -1;
    }

M
Minglei Jin 已提交
554 555 556 557 558 559 560 561 562 563 564
    i64 offset = pPager->pageSize * (pgno - 1);
    if (tdbOsLSeek(pPager->fd, offset, SEEK_SET) < 0) {
      ASSERT(0);
      return -1;
    }

    ret = tdbOsWrite(pPager->fd, pageBuf, pPager->pageSize);
    if (ret < 0) {
      ASSERT(0);
      return -1;
    }
565 566 567 568 569 570 571 572 573 574 575
  }

  tdbOsFSync(pPager->fd);

  tdbOsFree(pageBuf);

  tdbOsClose(jfd);
  tdbOsRemove(pPager->jFileName);

  return 0;
}