tdbPCache.c 5.1 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 22 23
struct SPCache {
  int             pageSize;
  int             cacheSize;
  int             extraSize;
  int             nRef;
  pthread_mutex_t mutex;
  int             nPage;
H
more  
Hongze Cheng 已提交
24
  SPgHdr          lru;
H
more  
Hongze Cheng 已提交
25 26
  int             nRecyclable;
  int             nHash;
H
more  
Hongze Cheng 已提交
27
  SPgHdr **       pgHash;
H
more  
Hongze Cheng 已提交
28 29
  int             nFree;
  SPgHdr *        pFree;
H
Hongze Cheng 已提交
30 31
};

H
more  
Hongze Cheng 已提交
32 33
#define PCACHE_PAGE_HASH(pgid) 0  // TODO
#define PAGE_IS_PINNED(pPage)  ((pPage)->pLruNext == NULL)
H
Hongze Cheng 已提交
34

H
more  
Hongze Cheng 已提交
35 36 37 38 39 40
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 已提交
41
static void    tdbPCachePinPage(SPgHdr *pPage);
H
more  
Hongze Cheng 已提交
42 43
static void    tdbPCacheRemovePageFromHash(SPgHdr *pPage);
static void    tdbPCacheAddPageToHash(SPgHdr *pPage);
H
Hongze Cheng 已提交
44

H
Hongze Cheng 已提交
45
int tdbPCacheOpen(int pageSize, int cacheSize, int extraSize, SPCache **ppCache) {
H
more  
Hongze Cheng 已提交
46 47 48
  SPCache *pCache;
  void *   pPtr;
  SPgHdr * pPgHdr;
H
Hongze Cheng 已提交
49

H
more  
Hongze Cheng 已提交
50 51
  pCache = (SPCache *)calloc(1, sizeof(*pCache));
  if (pCache == NULL) {
H
Hongze Cheng 已提交
52 53 54
    return -1;
  }

H
more  
Hongze Cheng 已提交
55 56 57
  pCache->pageSize = pageSize;
  pCache->cacheSize = cacheSize;
  pCache->extraSize = extraSize;
H
Hongze Cheng 已提交
58

H
more  
Hongze Cheng 已提交
59
  tdbPCacheInitLock(pCache);
H
Hongze Cheng 已提交
60

H
more  
Hongze Cheng 已提交
61 62 63 64
  for (int i = 0; i < cacheSize; i++) {
    pPtr = calloc(1, pageSize + extraSize + sizeof(SPgHdr));
    if (pPtr == NULL) {
      return -1;
H
Hongze Cheng 已提交
65 66
    }

H
more  
Hongze Cheng 已提交
67 68 69
    pPgHdr = (SPgHdr *)&((char *)pPtr)[pageSize + extraSize];
    pPgHdr->pFreeNext = pCache->pFree;
    pCache->pFree = pPgHdr;
H
Hongze Cheng 已提交
70

H
more  
Hongze Cheng 已提交
71
    pCache->nFree++;
H
Hongze Cheng 已提交
72 73 74 75 76
  }

  return 0;
}

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

H
more  
Hongze Cheng 已提交
82 83 84
SPgHdr *tdbPCacheFetch(SPCache *pCache, const SPgid *pPgid, bool alcNewPage) {
  SPgHdr *pPage;

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

  return pPage;
H
Hongze Cheng 已提交
90 91
}

H
Hongze Cheng 已提交
92
void tdbPCacheFetchFinish(SPCache *pCache, SPgHdr *pPage) {
H
more  
Hongze Cheng 已提交
93 94 95
  // TODO
}

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

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

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

H
Hongze Cheng 已提交
104 105 106 107 108 109 110 111
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 已提交
112 113 114 115 116 117 118 119 120 121 122 123
}

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) {
    if (memcmp(pPgid, &(pPage->pgid), sizeof(*pPgid)) == 0) break;
    pPage = pPage->pHashNext;
  }

H
more  
Hongze Cheng 已提交
124 125
  if (pPage || !alcNewPage) {
    if (pPage) tdbPCachePinPage(pPage);
H
more  
Hongze Cheng 已提交
126 127 128
    return pPage;
  }

H
more  
Hongze Cheng 已提交
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
  // 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);
  }

  // 4. Try a stress allocation

  // 5. Page here are just created from a free list
  // or by recycling or allocated streesly,
  // need to initialize it
  if (pPage) {
    memcpy(&pPage->pgid, pPgid, sizeof(*pPgid));
    pPage->pCache = pCache;
    pPage->pLruNext = NULL;
    tdbPCacheAddPageToHash(pPage);
  }

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

static void tdbPCachePinPage(SPgHdr *pPage) {
H
more  
Hongze Cheng 已提交
160 161 162 163 164 165 166 167 168
  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 已提交
169
  }
H
more  
Hongze Cheng 已提交
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
}

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 = PCACHE_PAGE_HASH(&pPage->pgid) % pCache->nHash;

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

  pCache->nPage++;
H
more  
Hongze Cheng 已提交
198
}