tdbPCache.c 6.5 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
more  
Hongze Cheng 已提交
17 18 19 20 21
struct SPCache {
  int             pageSize;
  int             cacheSize;
  int             extraSize;
  pthread_mutex_t mutex;
H
more  
Hongze Cheng 已提交
22 23
  int             nFree;
  SPgHdr *        pFree;
H
more  
Hongze Cheng 已提交
24 25
  int             nPage;
  int             nHash;
H
more  
Hongze Cheng 已提交
26
  SPgHdr **       pgHash;
H
more  
Hongze Cheng 已提交
27 28 29 30 31
  int             nRecyclable;
  SPgHdr          lru;
  int             nDirty;
  SPgHdr *        pDirty;
  SPgHdr *        pDirtyTail;
H
Hongze Cheng 已提交
32 33
};

H
more  
Hongze Cheng 已提交
34 35 36 37 38 39
#define PCACHE_PAGE_HASH(pPgid)                              \
  ({                                                         \
    u32 *t = (u32 *)((pPgid)->fileid);                       \
    t[0] + t[1] + t[2] + t[3] + t[4] + t[5] + (pPgid)->pgno; \
  })
#define PAGE_IS_PINNED(pPage) ((pPage)->pLruNext == NULL)
H
Hongze Cheng 已提交
40

H
more  
Hongze Cheng 已提交
41
static int     tdbPCacheOpenImpl(SPCache *pCache);
H
more  
Hongze Cheng 已提交
42 43 44 45 46 47
static void    tdbPCacheInitLock(SPCache *pCache);
static void    tdbPCacheClearLock(SPCache *pCache);
static void    tdbPCacheLock(SPCache *pCache);
static void    tdbPCacheUnlock(SPCache *pCache);
static bool    tdbPCacheLocked(SPCache *pCache);
static SPgHdr *tdbPCacheFetchImpl(SPCache *pCache, const SPgid *pPgid, bool alcNewPage);
H
more  
Hongze Cheng 已提交
48
static void    tdbPCachePinPage(SPgHdr *pPage);
H
more  
Hongze Cheng 已提交
49 50
static void    tdbPCacheRemovePageFromHash(SPgHdr *pPage);
static void    tdbPCacheAddPageToHash(SPgHdr *pPage);
H
Hongze Cheng 已提交
51

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

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

H
more  
Hongze Cheng 已提交
62 63 64
  pCache->pageSize = pageSize;
  pCache->cacheSize = cacheSize;
  pCache->extraSize = extraSize;
H
Hongze Cheng 已提交
65

H
more  
Hongze Cheng 已提交
66 67 68
  if (tdbPCacheOpenImpl(pCache) < 0) {
    free(pCache);
    return -1;
H
Hongze Cheng 已提交
69 70 71 72 73
  }

  return 0;
}

H
Hongze Cheng 已提交
74
int tdbPCacheClose(SPCache *pCache) {
H
Hongze Cheng 已提交
75
  /* TODO */
H
Hongze Cheng 已提交
76
  return 0;
H
Hongze Cheng 已提交
77 78
}

H
more  
Hongze Cheng 已提交
79 80 81
SPgHdr *tdbPCacheFetch(SPCache *pCache, const SPgid *pPgid, bool alcNewPage) {
  SPgHdr *pPage;

H
Hongze Cheng 已提交
82
  tdbPCacheLock(pCache);
H
more  
Hongze Cheng 已提交
83
  pPage = tdbPCacheFetchImpl(pCache, pPgid, alcNewPage);
H
Hongze Cheng 已提交
84
  tdbPCacheUnlock(pCache);
H
more  
Hongze Cheng 已提交
85 86

  return pPage;
H
Hongze Cheng 已提交
87 88
}

H
Hongze Cheng 已提交
89
void tdbPCacheFetchFinish(SPCache *pCache, SPgHdr *pPage) {
H
more  
Hongze Cheng 已提交
90 91
  /* TODO */
  pPage->nRef++;  // TODO: do we need atomic operation???
H
more  
Hongze Cheng 已提交
92 93
}

H
more  
Hongze Cheng 已提交
94
void tdbPCacheRelease(SPgHdr *pHdr) {
H
Hongze Cheng 已提交
95 96 97
  // TODO
}

H
more  
Hongze Cheng 已提交
98 99 100 101
static void tdbPCacheInitLock(SPCache *pCache) { pthread_mutex_init(&(pCache->mutex), NULL); }

static void tdbPCacheClearLock(SPCache *pCache) { pthread_mutex_destroy(&(pCache->mutex)); }

H
Hongze Cheng 已提交
102 103 104 105 106 107 108 109
static void tdbPCacheLock(SPCache *pCache) { pthread_mutex_lock(&(pCache->mutex)); }

static void tdbPCacheUnlock(SPCache *pCache) { pthread_mutex_unlock(&(pCache->mutex)); }

static bool tdbPCacheLocked(SPCache *pCache) {
  assert(0);
  // TODO
  return true;
H
more  
Hongze Cheng 已提交
110 111 112 113 114 115 116 117
}

static SPgHdr *tdbPCacheFetchImpl(SPCache *pCache, const SPgid *pPgid, bool alcNewPage) {
  SPgHdr *pPage;

  // 1. Search the hash table
  pPage = pCache->pgHash[PCACHE_PAGE_HASH(pPgid) % pCache->nHash];
  while (pPage) {
H
more  
Hongze Cheng 已提交
118
    if (TDB_IS_SAME_PAGE(&(pPage->pgid), pPgid)) break;
H
more  
Hongze Cheng 已提交
119 120 121
    pPage = pPage->pHashNext;
  }

H
more  
Hongze Cheng 已提交
122
  if (pPage || !alcNewPage) {
H
more  
Hongze Cheng 已提交
123 124 125 126
    if (pPage) {
      ASSERT(pPage->isLoad == 1);
      tdbPCachePinPage(pPage);
    }
H
more  
Hongze Cheng 已提交
127 128 129
    return pPage;
  }

H
more  
Hongze Cheng 已提交
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
  // 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;
    tdbPCacheRemovePageFromHash(pPage);
    tdbPCachePinPage(pPage);
  }

H
more  
Hongze Cheng 已提交
145
  // 4. Try a stress allocation (TODO)
H
more  
Hongze Cheng 已提交
146 147 148 149 150

  // 5. Page here are just created from a free list
  // or by recycling or allocated streesly,
  // need to initialize it
  if (pPage) {
H
more  
Hongze Cheng 已提交
151
    memcpy(&(pPage->pgid), pPgid, sizeof(*pPgid));
H
more  
Hongze Cheng 已提交
152
    pPage->pLruNext = NULL;
H
more  
Hongze Cheng 已提交
153
    pPage->isLoad = 0;
H
more  
Hongze Cheng 已提交
154 155 156
    tdbPCacheAddPageToHash(pPage);
  }

H
more  
Hongze Cheng 已提交
157
  return pPage;
H
more  
Hongze Cheng 已提交
158 159 160
}

static void tdbPCachePinPage(SPgHdr *pPage) {
H
more  
Hongze Cheng 已提交
161 162 163 164 165 166 167 168 169
  SPCache *pCache;

  pCache = pPage->pCache;
  if (!PAGE_IS_PINNED(pPage)) {
    pPage->pLruPrev->pLruNext = pPage->pLruNext;
    pPage->pLruNext->pLruPrev = pPage->pLruPrev;
    pPage->pLruNext = NULL;

    pCache->nRecyclable--;
H
more  
Hongze Cheng 已提交
170
  }
H
more  
Hongze Cheng 已提交
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
}

static void tdbPCacheRemovePageFromHash(SPgHdr *pPage) {
  SPCache *pCache;
  SPgHdr **ppPage;
  int      h;

  pCache = pPage->pCache;
  h = PCACHE_PAGE_HASH(&(pPage->pgid));
  for (ppPage = &(pCache->pgHash[h % pCache->nHash]); *ppPage != pPage; ppPage = &((*ppPage)->pHashNext))
    ;
  ASSERT(*ppPage == pPage);
  *ppPage = pPage->pHashNext;

  pCache->nPage--;
}

static void tdbPCacheAddPageToHash(SPgHdr *pPage) {
  SPCache *pCache;
  int      h;

  pCache = pPage->pCache;
H
more  
Hongze Cheng 已提交
193
  h = PCACHE_PAGE_HASH(&(pPage->pgid)) % pCache->nHash;
H
more  
Hongze Cheng 已提交
194 195 196 197 198

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

  pCache->nPage++;
H
more  
Hongze Cheng 已提交
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
}

static int tdbPCacheOpenImpl(SPCache *pCache) {
  SPgHdr *pPage;
  u8 *    pPtr;
  int     tsize;

  tdbPCacheInitLock(pCache);

  // Open the free list
  pCache->nFree = 0;
  pCache->pFree = NULL;
  for (int i = 0; i < pCache->cacheSize; i++) {
    tsize = pCache->pageSize + sizeof(SPgHdr) + pCache->extraSize;
    pPtr = (u8 *)calloc(1, tsize);
    if (pPtr == NULL) {
      // TODO
      return -1;
    }

    pPage = (SPgHdr *)(&(pPtr[pCache->pageSize]));
    pPage->pData = (void *)pPtr;
    pPage->pExtra = (void *)(&(pPage[1]));
    // pPage->pgid = 0;
    pPage->isAnchor = 0;
    pPage->isLocalPage = 1;
    pPage->pCache = pCache;
    pPage->pHashNext = NULL;
    pPage->pLruNext = NULL;
    pPage->pLruPrev = NULL;

    pPage->pFreeNext = pCache->pFree;
    pCache->pFree = pPage;
    pCache->nFree++;
  }

  // Open the hash table
  pCache->nPage = 0;
  pCache->nHash = pCache->cacheSize;
  pCache->pgHash = (SPgHdr **)calloc(pCache->nHash, sizeof(SPgHdr *));
  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);

  // Open dirty list
  pCache->nDirty = 0;
  pCache->pDirty = pCache->pDirtyTail = NULL;

  return 0;
H
more  
Hongze Cheng 已提交
255
}