tdbPCache.c 14.3 KB
Newer Older
H
refact  
Hongze Cheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * 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
Hongze Cheng 已提交
15 16
#include "tdbInt.h"

H
Hongze Cheng 已提交
17 18
// #include <sys/types.h>
// #include <unistd.h>
H
Hongze Cheng 已提交
19

H
more  
Hongze Cheng 已提交
20
struct SPCache {
H
Hongze Cheng 已提交
21 22 23
  int         szPage;
  int         nPages;
  SPage     **aPage;
H
Hongze Cheng 已提交
24 25 26 27 28 29 30 31
  tdb_mutex_t mutex;
  int         nFree;
  SPage      *pFree;
  int         nPage;
  int         nHash;
  SPage     **pgHash;
  int         nRecyclable;
  SPage       lru;
H
Hongze Cheng 已提交
32 33
};

wafwerar's avatar
wafwerar 已提交
34 35 36
static inline uint32_t tdbPCachePageHash(const SPgid *pPgid) {
  uint32_t *t = (uint32_t *)((pPgid)->fileid);
  return (uint32_t)(t[0] + t[1] + t[2] + t[3] + t[4] + t[5] + (pPgid)->pgno);
wafwerar's avatar
wafwerar 已提交
37
}
H
Hongze Cheng 已提交
38

H
refact  
Hongze Cheng 已提交
39
static int    tdbPCacheOpenImpl(SPCache *pCache);
H
Hongze Cheng 已提交
40
static SPage *tdbPCacheFetchImpl(SPCache *pCache, const SPgid *pPgid, TXN *pTxn);
H
Hongze Cheng 已提交
41 42 43 44
static void   tdbPCachePinPage(SPCache *pCache, SPage *pPage);
static void   tdbPCacheRemovePageFromHash(SPCache *pCache, SPage *pPage);
static void   tdbPCacheAddPageToHash(SPCache *pCache, SPage *pPage);
static void   tdbPCacheUnpinPage(SPCache *pCache, SPage *pPage);
H
Hongze Cheng 已提交
45 46 47 48 49 50
static int    tdbPCacheCloseImpl(SPCache *pCache);

static void tdbPCacheInitLock(SPCache *pCache) { tdbMutexInit(&(pCache->mutex), NULL); }
static void tdbPCacheDestroyLock(SPCache *pCache) { tdbMutexDestroy(&(pCache->mutex)); }
static void tdbPCacheLock(SPCache *pCache) { tdbMutexLock(&(pCache->mutex)); }
static void tdbPCacheUnlock(SPCache *pCache) { tdbMutexUnlock(&(pCache->mutex)); }
H
Hongze Cheng 已提交
51

H
Hongze Cheng 已提交
52
int tdbPCacheOpen(int pageSize, int cacheSize, SPCache **ppCache) {
H
more  
Hongze Cheng 已提交
53
  SPCache *pCache;
H
Hongze Cheng 已提交
54 55
  void    *pPtr;
  SPage   *pPgHdr;
H
Hongze Cheng 已提交
56

H
Hongze Cheng 已提交
57
  pCache = (SPCache *)tdbOsCalloc(1, sizeof(*pCache) + sizeof(SPage *) * cacheSize);
H
more  
Hongze Cheng 已提交
58
  if (pCache == NULL) {
H
Hongze Cheng 已提交
59 60 61
    return -1;
  }

H
Hongze Cheng 已提交
62 63
  pCache->szPage = pageSize;
  pCache->nPages = cacheSize;
H
Hongze Cheng 已提交
64 65 66 67 68
  pCache->aPage = (SPage **)tdbOsCalloc(cacheSize, sizeof(SPage *));
  if (pCache->aPage == NULL) {
    tdbOsFree(pCache);
    return -1;
  }
H
Hongze Cheng 已提交
69

H
more  
Hongze Cheng 已提交
70
  if (tdbPCacheOpenImpl(pCache) < 0) {
H
Hongze Cheng 已提交
71
    tdbOsFree(pCache);
H
more  
Hongze Cheng 已提交
72
    return -1;
H
Hongze Cheng 已提交
73 74
  }

H
more  
Hongze Cheng 已提交
75
  *ppCache = pCache;
H
Hongze Cheng 已提交
76 77 78
  return 0;
}

H
Hongze Cheng 已提交
79
int tdbPCacheClose(SPCache *pCache) {
H
Hongze Cheng 已提交
80 81
  if (pCache) {
    tdbPCacheCloseImpl(pCache);
H
Hongze Cheng 已提交
82
    tdbOsFree(pCache->aPage);
H
Hongze Cheng 已提交
83 84
    tdbOsFree(pCache);
  }
H
Hongze Cheng 已提交
85
  return 0;
H
Hongze Cheng 已提交
86 87
}

H
Hongze Cheng 已提交
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
// TODO:
// if (pPage->id >= pCache->nPages) {
//   free(pPage);
//   pCache->aPage[pPage->id] = NULL;
// } else {
//   add to free list
// }

static int tdbPCacheAlterImpl(SPCache *pCache, int32_t nPage) {
  if (pCache->nPages == nPage) {
    return 0;
  } else if (pCache->nPages < nPage) {
    SPage **aPage = tdbOsCalloc(nPage, sizeof(SPage *));
    if (aPage == NULL) {
      return -1;
    }

H
Hongze Cheng 已提交
105
    for (int32_t iPage = pCache->nPages; iPage < nPage; iPage++) {
H
Hongze Cheng 已提交
106 107
      if (tdbPageCreate(pCache->szPage, &aPage[iPage], tdbDefaultMalloc, NULL) < 0) {
        // TODO: handle error
M
Minglei Jin 已提交
108
        tdbOsFree(aPage);
H
Hongze Cheng 已提交
109 110 111 112 113 114 115 116 117 118 119 120
        return -1;
      }

      // pPage->pgid = 0;
      aPage[iPage]->isAnchor = 0;
      aPage[iPage]->isLocal = 1;
      aPage[iPage]->nRef = 0;
      aPage[iPage]->pHashNext = NULL;
      aPage[iPage]->pLruNext = NULL;
      aPage[iPage]->pLruPrev = NULL;
      aPage[iPage]->pDirtyNext = NULL;

H
Hongze Cheng 已提交
121 122 123 124 125 126
      // add to local list
      aPage[iPage]->id = iPage;
    }

    // add page to free list
    for (int32_t iPage = pCache->nPages; iPage < nPage; iPage++) {
H
Hongze Cheng 已提交
127 128 129 130 131
      aPage[iPage]->pFreeNext = pCache->pFree;
      pCache->pFree = aPage[iPage];
      pCache->nFree++;
    }

132
    for (int32_t iPage = 0; iPage < pCache->nPages; iPage++) {
H
Hongze Cheng 已提交
133 134 135 136 137
      aPage[iPage] = pCache->aPage[iPage];
    }

    tdbOsFree(pCache->aPage);
    pCache->aPage = aPage;
H
Hongze Cheng 已提交
138 139 140 141 142
  } else {
    for (SPage **ppPage = &pCache->pFree; *ppPage;) {
      int32_t iPage = (*ppPage)->id;

      if (iPage >= nPage) {
H
Hongze Cheng 已提交
143 144 145 146
        SPage *pPage = *ppPage;
        *ppPage = pPage->pFreeNext;
        pCache->aPage[pPage->id] = NULL;
        tdbPageDestroy(pPage, tdbDefaultFree, NULL);
H
Hongze Cheng 已提交
147 148 149 150 151
        pCache->nFree--;
      } else {
        ppPage = &(*ppPage)->pFreeNext;
      }
    }
H
Hongze Cheng 已提交
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
  }

  pCache->nPages = nPage;
  return 0;
}

int tdbPCacheAlter(SPCache *pCache, int32_t nPage) {
  int ret = 0;

  tdbPCacheLock(pCache);

  ret = tdbPCacheAlterImpl(pCache, nPage);

  tdbPCacheUnlock(pCache);

  return ret;
}

H
Hongze Cheng 已提交
170
SPage *tdbPCacheFetch(SPCache *pCache, const SPgid *pPgid, TXN *pTxn) {
H
refact  
Hongze Cheng 已提交
171
  SPage *pPage;
172
  i32    nRef = 0;
H
more  
Hongze Cheng 已提交
173

H
Hongze Cheng 已提交
174
  tdbPCacheLock(pCache);
H
Hongze Cheng 已提交
175

H
Hongze Cheng 已提交
176
  pPage = tdbPCacheFetchImpl(pCache, pPgid, pTxn);
H
Hongze Cheng 已提交
177
  if (pPage) {
H
Hongze Cheng 已提交
178
    nRef = tdbRefPage(pPage);
H
Hongze Cheng 已提交
179 180
  }

H
Hongze Cheng 已提交
181
  tdbPCacheUnlock(pCache);
H
more  
Hongze Cheng 已提交
182

H
Hongze Cheng 已提交
183 184 185
  // printf("thread %" PRId64 " fetch page %d pgno %d pPage %p nRef %d\n", taosGetSelfPthreadId(), pPage->id,
  //        TDB_PAGE_PGNO(pPage), pPage, nRef);

186
  if (pPage) {
187
    tdbTrace("pcache/fetch page %p/%d/%d/%d", pPage, TDB_PAGE_PGNO(pPage), pPage->id, nRef);
188
  } else {
189
    tdbTrace("pcache/fetch page %p", pPage);
190 191
  }

H
more  
Hongze Cheng 已提交
192
  return pPage;
H
Hongze Cheng 已提交
193 194
}

M
Minglei Jin 已提交
195 196 197 198 199 200 201 202 203 204 205 206 207
void tdbPCacheMarkFree(SPCache *pCache, SPage *pPage) {
  tdbPCacheLock(pCache);
  tdbPCacheRemovePageFromHash(pCache, pPage);
  pPage->isFree = 1;
  tdbPCacheUnlock(pCache);
}

static void tdbPCacheFreePage(SPCache *pCache, SPage *pPage) {
  if (pPage->id < pCache->nPages) {
    pPage->pFreeNext = pCache->pFree;
    pCache->pFree = pPage;
    pPage->isFree = 0;
    ++pCache->nFree;
208
    tdbTrace("pcache/free page %p/%d, pgno:%d, ", pPage, pPage->id, TDB_PAGE_PGNO(pPage));
M
Minglei Jin 已提交
209
  } else {
210
    tdbTrace("pcache/free2 page: %p/%d, pgno:%d, ", pPage, pPage->id, TDB_PAGE_PGNO(pPage));
M
Minglei Jin 已提交
211 212 213 214 215 216

    tdbPCacheRemovePageFromHash(pCache, pPage);
    tdbPageDestroy(pPage, tdbDefaultFree, NULL);
  }
}

217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
void tdbPCacheInvalidatePage(SPCache *pCache, SPager *pPager, SPgno pgno) {
  SPgid        pgid;
  const SPgid *pPgid = &pgid;
  SPage       *pPage = NULL;

  memcpy(&pgid, pPager->fid, TDB_FILE_ID_LEN);
  pgid.pgno = pgno;

  pPage = pCache->pgHash[tdbPCachePageHash(pPgid) % pCache->nHash];
  while (pPage) {
    if (pPage->pgid.pgno == pPgid->pgno && memcmp(pPage->pgid.fileid, pPgid->fileid, TDB_FILE_ID_LEN) == 0) break;
    pPage = pPage->pHashNext;
  }

  if (pPage) {
    tdbPCacheRemovePageFromHash(pCache, pPage);
  }
}

H
Hongze Cheng 已提交
236
void tdbPCacheRelease(SPCache *pCache, SPage *pPage, TXN *pTxn) {
H
Hongze Cheng 已提交
237 238
  i32 nRef;

239 240 241 242
  if (!pTxn) {
    tdbError("tdb/pcache: null ptr pTxn, release failed.");
    return;
  }
H
Hongze Cheng 已提交
243

H
Hongze Cheng 已提交
244 245
  tdbPCacheLock(pCache);
  nRef = tdbUnrefPage(pPage);
246
  tdbTrace("pcache/release page %p/%d/%d/%d", pPage, TDB_PAGE_PGNO(pPage), pPage->id, nRef);
H
Hongze Cheng 已提交
247
  if (nRef == 0) {
H
Hongze Cheng 已提交
248 249
    // test the nRef again to make sure
    // it is safe th handle the page
H
Hongze Cheng 已提交
250 251 252
    // nRef = tdbGetPageRef(pPage);
    // if (nRef == 0) {
    if (pPage->isLocal) {
M
Minglei Jin 已提交
253 254 255 256 257
      if (!pPage->isFree) {
        tdbPCacheUnpinPage(pCache, pPage);
      } else {
        tdbPCacheFreePage(pCache, pPage);
      }
H
Hongze Cheng 已提交
258 259 260 261
    } else {
      if (TDB_TXN_IS_WRITE(pTxn)) {
        // remove from hash
        tdbPCacheRemovePageFromHash(pCache, pPage);
H
Hongze Cheng 已提交
262 263
      }

H
Hongze Cheng 已提交
264 265 266
      tdbPageDestroy(pPage, pTxn->xFree, pTxn->xArg);
    }
    // }
H
more  
Hongze Cheng 已提交
267
  }
H
Hongze Cheng 已提交
268
  tdbPCacheUnlock(pCache);
H
Hongze Cheng 已提交
269 270
}

H
Hongze Cheng 已提交
271
int tdbPCacheGetPageSize(SPCache *pCache) { return pCache->szPage; }
H
more  
Hongze Cheng 已提交
272

H
Hongze Cheng 已提交
273
static SPage *tdbPCacheFetchImpl(SPCache *pCache, const SPgid *pPgid, TXN *pTxn) {
H
Hongze Cheng 已提交
274 275 276 277
  int    ret = 0;
  SPage *pPage = NULL;
  SPage *pPageH = NULL;

278 279 280 281
  if (!pTxn) {
    tdbError("tdb/pcache: null ptr pTxn, fetch impl failed.");
    return NULL;
  }
H
more  
Hongze Cheng 已提交
282 283

  // 1. Search the hash table
wafwerar's avatar
wafwerar 已提交
284
  pPage = pCache->pgHash[tdbPCachePageHash(pPgid) % pCache->nHash];
H
more  
Hongze Cheng 已提交
285
  while (pPage) {
286
    if (pPage->pgid.pgno == pPgid->pgno && memcmp(pPage->pgid.fileid, pPgid->fileid, TDB_FILE_ID_LEN) == 0) break;
H
more  
Hongze Cheng 已提交
287 288 289
    pPage = pPage->pHashNext;
  }

H
refact  
Hongze Cheng 已提交
290
  if (pPage) {
H
Hongze Cheng 已提交
291 292 293 294
    if (pPage->isLocal || TDB_TXN_IS_WRITE(pTxn)) {
      tdbPCachePinPage(pCache, pPage);
      return pPage;
    }
H
more  
Hongze Cheng 已提交
295 296
  }

H
Hongze Cheng 已提交
297 298 299 300 301
  // 1. pPage == NULL
  // 2. pPage && pPage->isLocal == 0 && !TDB_TXN_IS_WRITE(pTxn)
  pPageH = pPage;
  pPage = NULL;

H
more  
Hongze Cheng 已提交
302 303 304 305 306 307 308 309 310 311 312
  // 2. Try to allocate a new page from the free list
  if (pCache->pFree) {
    pPage = pCache->pFree;
    pCache->pFree = pPage->pFreeNext;
    pCache->nFree--;
    pPage->pLruNext = NULL;
  }

  // 3. Try to Recycle a page
  if (!pPage && !pCache->lru.pLruPrev->isAnchor) {
    pPage = pCache->lru.pLruPrev;
H
Hongze Cheng 已提交
313 314
    tdbPCacheRemovePageFromHash(pCache, pPage);
    tdbPCachePinPage(pCache, pPage);
H
more  
Hongze Cheng 已提交
315 316
  }

H
Hongze Cheng 已提交
317
  // 4. Try a create new page
318
  if (!pPage && pTxn->xMalloc != NULL) {
H
Hongze Cheng 已提交
319
    ret = tdbPageCreate(pCache->szPage, &pPage, pTxn->xMalloc, pTxn->xArg);
M
Minglei Jin 已提交
320
    if (ret < 0 || pPage == NULL) {
321 322
      tdbError("tdb/pcache: ret: %" PRId32 " pPage: %p, page create failed.", ret, pPage);
      // TODO: recycle other backup pages
H
Hongze Cheng 已提交
323 324 325 326 327 328
      return NULL;
    }

    // init the page fields
    pPage->isAnchor = 0;
    pPage->isLocal = 0;
H
Hongze Cheng 已提交
329 330
    pPage->nRef = 0;
    pPage->id = -1;
H
Hongze Cheng 已提交
331
  }
H
more  
Hongze Cheng 已提交
332 333 334 335 336

  // 5. Page here are just created from a free list
  // or by recycling or allocated streesly,
  // need to initialize it
  if (pPage) {
H
Hongze Cheng 已提交
337 338 339
    if (pPageH) {
      // copy the page content
      memcpy(&(pPage->pgid), pPgid, sizeof(*pPgid));
340 341 342 343 344 345 346 347 348

      for (int nLoops = 0;;) {
        if (pPageH->pPager) break;
        if (++nLoops > 1000) {
          sched_yield();
          nLoops = 0;
        }
      }

H
Hongze Cheng 已提交
349 350 351 352
      pPage->pLruNext = NULL;
      pPage->pPager = pPageH->pPager;

      memcpy(pPage->pData, pPageH->pData, pPage->pageSize);
353 354
      // tdbDebug("pcache/pPageH: %p %ld %p %p %u", pPageH, pPageH->pPageHdr - pPageH->pData, pPageH->xCellSize, pPage,
      //         TDB_PAGE_PGNO(pPageH));
H
Hongze Cheng 已提交
355
      tdbPageInit(pPage, pPageH->pPageHdr - pPageH->pData, pPageH->xCellSize);
H
Hongze Cheng 已提交
356 357 358 359
      pPage->kLen = pPageH->kLen;
      pPage->vLen = pPageH->vLen;
      pPage->maxLocal = pPageH->maxLocal;
      pPage->minLocal = pPageH->minLocal;
H
Hongze Cheng 已提交
360 361 362 363 364 365 366 367 368
    } else {
      memcpy(&(pPage->pgid), pPgid, sizeof(*pPgid));
      pPage->pLruNext = NULL;
      pPage->pPager = NULL;

      if (pPage->isLocal || TDB_TXN_IS_WRITE(pTxn)) {
        tdbPCacheAddPageToHash(pCache, pPage);
      }
    }
H
more  
Hongze Cheng 已提交
369 370
  }

H
more  
Hongze Cheng 已提交
371
  return pPage;
H
more  
Hongze Cheng 已提交
372 373
}

H
Hongze Cheng 已提交
374
static void tdbPCachePinPage(SPCache *pCache, SPage *pPage) {
H
Hongze Cheng 已提交
375
  if (pPage->pLruNext != NULL) {
376 377 378 379 380
    int32_t nRef = tdbGetPageRef(pPage);
    if (nRef != 0) {
      tdbError("tdb/pcache: pin page's ref not zero: %" PRId32, nRef);
      return;
    }
H
Hongze Cheng 已提交
381

H
more  
Hongze Cheng 已提交
382 383 384 385 386
    pPage->pLruPrev->pLruNext = pPage->pLruNext;
    pPage->pLruNext->pLruPrev = pPage->pLruPrev;
    pPage->pLruNext = NULL;

    pCache->nRecyclable--;
H
Hongze Cheng 已提交
387

388
    tdbTrace("pcache/pin page %p/%d, pgno:%d, ", pPage, pPage->id, TDB_PAGE_PGNO(pPage));
H
more  
Hongze Cheng 已提交
389
  }
H
more  
Hongze Cheng 已提交
390 391
}

H
Hongze Cheng 已提交
392
static void tdbPCacheUnpinPage(SPCache *pCache, SPage *pPage) {
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
  i32 nRef = tdbGetPageRef(pPage);
  if (nRef != 0) {
    tdbError("tdb/pcache: unpin page's ref not zero: %" PRId32, nRef);
    return;
  }
  if (!pPage->isLocal) {
    tdbError("tdb/pcache: unpin page's not local: %" PRIu8, pPage->isLocal);
    return;
  }
  if (pPage->isDirty) {
    tdbError("tdb/pcache: unpin page's dirty: %" PRIu8, pPage->isDirty);
    return;
  }
  if (NULL != pPage->pLruNext) {
    tdbError("tdb/pcache: unpin page's pLruNext not null.");
    return;
  }
H
more  
Hongze Cheng 已提交
410

411 412
  tdbTrace("pCache:%p unpin page %p/%d, nPages:%d, pgno:%d, ", pCache, pPage, pPage->id, pCache->nPages,
           TDB_PAGE_PGNO(pPage));
H
Hongze Cheng 已提交
413 414 415 416 417
  if (pPage->id < pCache->nPages) {
    pPage->pLruPrev = &(pCache->lru);
    pPage->pLruNext = pCache->lru.pLruNext;
    pCache->lru.pLruNext->pLruPrev = pPage;
    pCache->lru.pLruNext = pPage;
H
more  
Hongze Cheng 已提交
418

H
Hongze Cheng 已提交
419
    pCache->nRecyclable++;
H
Hongze Cheng 已提交
420

H
Hongze Cheng 已提交
421
    // printf("unpin page %d pgno %d pPage %p\n", pPage->id, TDB_PAGE_PGNO(pPage), pPage);
422
    tdbTrace("pcache/unpin page %p/%d/%d", pPage, TDB_PAGE_PGNO(pPage), pPage->id);
H
Hongze Cheng 已提交
423
  } else {
424
    tdbTrace("pcache destroy page: %p/%d/%d", pPage, TDB_PAGE_PGNO(pPage), pPage->id);
H
Hongze Cheng 已提交
425 426 427 428

    tdbPCacheRemovePageFromHash(pCache, pPage);
    tdbPageDestroy(pPage, tdbDefaultFree, NULL);
  }
H
more  
Hongze Cheng 已提交
429 430
}

H
Hongze Cheng 已提交
431
static void tdbPCacheRemovePageFromHash(SPCache *pCache, SPage *pPage) {
432 433 434
  uint32_t h = tdbPCachePageHash(&(pPage->pgid)) % pCache->nHash;

  SPage **ppPage = &(pCache->pgHash[h]);
435 436 437
  for (; (*ppPage) && *ppPage != pPage; ppPage = &((*ppPage)->pHashNext))
    ;

H
Hongze Cheng 已提交
438
  if (*ppPage) {
439 440
    *ppPage = pPage->pHashNext;
    pCache->nPage--;
H
Hongze Cheng 已提交
441 442
    // printf("rmv page %d to hash, pgno %d, pPage %p\n", pPage->id, TDB_PAGE_PGNO(pPage), pPage);
  }
H
Hongze Cheng 已提交
443

444
  tdbTrace("pcache/remove page %p/%d from hash %" PRIu32 " pgno:%d, ", pPage, pPage->id, h, TDB_PAGE_PGNO(pPage));
H
more  
Hongze Cheng 已提交
445 446
}

H
Hongze Cheng 已提交
447
static void tdbPCacheAddPageToHash(SPCache *pCache, SPage *pPage) {
448
  uint32_t h = tdbPCachePageHash(&(pPage->pgid)) % pCache->nHash;
H
more  
Hongze Cheng 已提交
449 450 451 452 453

  pPage->pHashNext = pCache->pgHash[h];
  pCache->pgHash[h] = pPage;

  pCache->nPage++;
H
Hongze Cheng 已提交
454

455
  tdbTrace("pcache/add page %p/%d to hash %" PRIu32 " pgno:%d, ", pPage, pPage->id, h, TDB_PAGE_PGNO(pPage));
H
more  
Hongze Cheng 已提交
456 457 458
}

static int tdbPCacheOpenImpl(SPCache *pCache) {
H
refact  
Hongze Cheng 已提交
459
  SPage *pPage;
H
Hongze Cheng 已提交
460
  u8    *pPtr;
H
refact  
Hongze Cheng 已提交
461
  int    tsize;
H
Hongze Cheng 已提交
462
  int    ret;
H
more  
Hongze Cheng 已提交
463 464 465 466 467 468

  tdbPCacheInitLock(pCache);

  // Open the free list
  pCache->nFree = 0;
  pCache->pFree = NULL;
H
Hongze Cheng 已提交
469
  for (int i = 0; i < pCache->nPages; i++) {
H
Hongze Cheng 已提交
470
    if (tdbPageCreate(pCache->szPage, &pPage, tdbDefaultMalloc, NULL) < 0) {
H
Hongze Cheng 已提交
471
      // TODO: handle error
H
more  
Hongze Cheng 已提交
472 473 474 475 476
      return -1;
    }

    // pPage->pgid = 0;
    pPage->isAnchor = 0;
H
Hongze Cheng 已提交
477
    pPage->isLocal = 1;
H
Hongze Cheng 已提交
478
    pPage->nRef = 0;
H
more  
Hongze Cheng 已提交
479 480 481
    pPage->pHashNext = NULL;
    pPage->pLruNext = NULL;
    pPage->pLruPrev = NULL;
H
more  
Hongze Cheng 已提交
482
    pPage->pDirtyNext = NULL;
H
more  
Hongze Cheng 已提交
483

H
Hongze Cheng 已提交
484
    // add page to free list
H
more  
Hongze Cheng 已提交
485 486 487
    pPage->pFreeNext = pCache->pFree;
    pCache->pFree = pPage;
    pCache->nFree++;
H
Hongze Cheng 已提交
488 489

    // add to local list
H
Hongze Cheng 已提交
490 491
    pPage->id = i;
    pCache->aPage[i] = pPage;
H
more  
Hongze Cheng 已提交
492 493 494 495
  }

  // Open the hash table
  pCache->nPage = 0;
H
Hongze Cheng 已提交
496
  pCache->nHash = pCache->nPages < 8 ? 8 : pCache->nPages;
H
Hongze Cheng 已提交
497
  pCache->pgHash = (SPage **)tdbOsCalloc(pCache->nHash, sizeof(SPage *));
H
more  
Hongze Cheng 已提交
498 499 500 501 502 503 504 505 506 507 508 509
  if (pCache->pgHash == NULL) {
    // TODO
    return -1;
  }

  // Open LRU list
  pCache->nRecyclable = 0;
  pCache->lru.isAnchor = 1;
  pCache->lru.pLruNext = &(pCache->lru);
  pCache->lru.pLruPrev = &(pCache->lru);

  return 0;
H
Hongze Cheng 已提交
510 511
}

H
Hongze Cheng 已提交
512
static int tdbPCacheCloseImpl(SPCache *pCache) {
H
Hongze Cheng 已提交
513 514 515 516 517 518 519 520 521 522 523 524
  // free free page
  for (SPage *pPage = pCache->pFree; pPage;) {
    SPage *pPageT = pPage->pFreeNext;
    tdbPageDestroy(pPage, tdbDefaultFree, NULL);
    pPage = pPageT;
  }

  for (int32_t iBucket = 0; iBucket < pCache->nHash; iBucket++) {
    for (SPage *pPage = pCache->pgHash[iBucket]; pPage;) {
      SPage *pPageT = pPage->pHashNext;
      tdbPageDestroy(pPage, tdbDefaultFree, NULL);
      pPage = pPageT;
H
Hongze Cheng 已提交
525
    }
H
Hongze Cheng 已提交
526 527
  }

H
Hongze Cheng 已提交
528
  tdbOsFree(pCache->pgHash);
H
Hongze Cheng 已提交
529
  tdbPCacheDestroyLock(pCache);
wmmhello's avatar
wmmhello 已提交
530
  return 0;
H
Hongze Cheng 已提交
531
}