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
  int             nFree;
H
refact  
Hongze Cheng 已提交
23
  SPage *         pFree;
H
more  
Hongze Cheng 已提交
24 25
  int             nPage;
  int             nHash;
H
refact  
Hongze Cheng 已提交
26
  SPage **        pgHash;
H
more  
Hongze Cheng 已提交
27
  int             nRecyclable;
H
refact  
Hongze Cheng 已提交
28
  SPage           lru;
H
more  
Hongze Cheng 已提交
29
  int             nDirty;
H
refact  
Hongze Cheng 已提交
30 31
  SPage *         pDirty;
  SPage *         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
refact  
Hongze Cheng 已提交
41 42 43 44 45 46 47 48 49 50
static int    tdbPCacheOpenImpl(SPCache *pCache);
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 SPage *tdbPCacheFetchImpl(SPCache *pCache, const SPgid *pPgid, bool alcNewPage);
static void   tdbPCachePinPage(SPage *pPage);
static void   tdbPCacheRemovePageFromHash(SPage *pPage);
static void   tdbPCacheAddPageToHash(SPage *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
  SPCache *pCache;
  void *   pPtr;
H
refact  
Hongze Cheng 已提交
55
  SPage *  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
  }

H
more  
Hongze Cheng 已提交
71
  *ppCache = pCache;
H
Hongze Cheng 已提交
72 73 74
  return 0;
}

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

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

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

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

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

H
refact  
Hongze Cheng 已提交
95
void tdbPCacheRelease(SPage *pHdr) {
H
Hongze Cheng 已提交
96 97 98
  // TODO
}

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

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

H
Hongze Cheng 已提交
103 104 105 106 107 108 109 110
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 已提交
111 112
}

H
refact  
Hongze Cheng 已提交
113 114
static SPage *tdbPCacheFetchImpl(SPCache *pCache, const SPgid *pPgid, bool alcNewPage) {
  SPage *pPage;
H
more  
Hongze Cheng 已提交
115 116 117 118

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

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

H
more  
Hongze Cheng 已提交
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
  // 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 已提交
146
  // 4. Try a stress allocation (TODO)
H
more  
Hongze Cheng 已提交
147 148 149 150 151

  // 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 已提交
152
    memcpy(&(pPage->pgid), pPgid, sizeof(*pPgid));
H
more  
Hongze Cheng 已提交
153
    pPage->pLruNext = NULL;
H
more  
Hongze Cheng 已提交
154
    pPage->isLoad = 0;
H
more  
Hongze Cheng 已提交
155 156 157
    tdbPCacheAddPageToHash(pPage);
  }

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

H
refact  
Hongze Cheng 已提交
161
static void tdbPCachePinPage(SPage *pPage) {
H
more  
Hongze Cheng 已提交
162 163 164 165 166 167 168 169 170
  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 已提交
171
  }
H
more  
Hongze Cheng 已提交
172 173
}

H
refact  
Hongze Cheng 已提交
174
static void tdbPCacheRemovePageFromHash(SPage *pPage) {
H
more  
Hongze Cheng 已提交
175
  SPCache *pCache;
H
refact  
Hongze Cheng 已提交
176
  SPage ** ppPage;
H
more  
Hongze Cheng 已提交
177 178 179 180 181 182 183 184 185 186 187 188
  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--;
}

H
refact  
Hongze Cheng 已提交
189
static void tdbPCacheAddPageToHash(SPage *pPage) {
H
more  
Hongze Cheng 已提交
190 191 192 193
  SPCache *pCache;
  int      h;

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

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

  pCache->nPage++;
H
more  
Hongze Cheng 已提交
200 201 202
}

static int tdbPCacheOpenImpl(SPCache *pCache) {
H
refact  
Hongze Cheng 已提交
203 204 205
  SPage *pPage;
  u8 *   pPtr;
  int    tsize;
H
more  
Hongze Cheng 已提交
206 207 208 209 210 211 212

  tdbPCacheInitLock(pCache);

  // Open the free list
  pCache->nFree = 0;
  pCache->pFree = NULL;
  for (int i = 0; i < pCache->cacheSize; i++) {
H
refact  
Hongze Cheng 已提交
213
    tsize = pCache->pageSize + sizeof(SPage) + pCache->extraSize;
H
more  
Hongze Cheng 已提交
214 215 216 217 218 219
    pPtr = (u8 *)calloc(1, tsize);
    if (pPtr == NULL) {
      // TODO
      return -1;
    }

H
refact  
Hongze Cheng 已提交
220
    pPage = (SPage *)(&(pPtr[pCache->pageSize]));
H
more  
Hongze Cheng 已提交
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
    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;
H
refact  
Hongze Cheng 已提交
239
  pCache->pgHash = (SPage **)calloc(pCache->nHash, sizeof(SPage *));
H
more  
Hongze Cheng 已提交
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
  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 已提交
256
}