tdbPager.c 7.2 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
refact  
Hongze Cheng 已提交
18
struct SPager {
H
Hongze Cheng 已提交
19 20
  char    *dbFileName;
  char    *jFileName;
H
Hongze Cheng 已提交
21
  int      pageSize;
H
more  
Hongze Cheng 已提交
22 23 24 25 26 27
  uint8_t  fid[TDB_FILE_ID_LEN];
  int      fd;
  int      jfd;
  SPCache *pCache;
  SPgno    dbFileSize;
  SPgno    dbOrigSize;
H
more  
Hongze Cheng 已提交
28
  int      nDirty;
H
Hongze Cheng 已提交
29 30
  SPage   *pDirty;
  SPage   *pDirtyTail;
H
more  
Hongze Cheng 已提交
31
  u8       inTran;
H
more  
Hongze Cheng 已提交
32 33
};

H
Hongze Cheng 已提交
34 35 36 37 38 39
typedef struct __attribute__((__packed__)) {
  u8    hdrString[16];
  u16   pageSize;
  SPgno freePage;
  u32   nFreePages;
  u8    reserved[102];
H
Hongze Cheng 已提交
40 41
} SFileHdr;

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

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

H
refact  
Hongze Cheng 已提交
46
static int tdbPagerReadPage(SPager *pPager, SPage *pPage);
H
Hongze Cheng 已提交
47
static int tdbPagerAllocPage(SPager *pPager, SPgno *ppgno);
H
Hongze Cheng 已提交
48
static int tdbPagerInitPage(SPager *pPager, SPage *pPage, int (*initPage)(SPage *, void *), void *arg);
H
Hongze Cheng 已提交
49

H
refact  
Hongze Cheng 已提交
50
int tdbPagerOpen(SPCache *pCache, const char *fileName, SPager **ppPager) {
H
more  
Hongze Cheng 已提交
51
  uint8_t *pPtr;
H
Hongze Cheng 已提交
52
  SPager  *pPager;
H
more  
Hongze Cheng 已提交
53 54
  int      fsize;
  int      zsize;
H
Hongze Cheng 已提交
55
  int      ret;
H
more  
Hongze Cheng 已提交
56

H
refact  
Hongze Cheng 已提交
57
  *ppPager = NULL;
H
more  
Hongze Cheng 已提交
58 59

  fsize = strlen(fileName);
H
refact  
Hongze Cheng 已提交
60
  zsize = sizeof(*pPager)  /* SPager */
H
more  
Hongze Cheng 已提交
61 62 63 64 65 66 67
          + fsize + 1      /* dbFileName */
          + fsize + 8 + 1; /* jFileName */
  pPtr = (uint8_t *)calloc(1, zsize);
  if (pPtr == NULL) {
    return -1;
  }

H
refact  
Hongze Cheng 已提交
68 69 70 71 72 73
  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 已提交
74
  pPtr += fsize + 1;
H
refact  
Hongze Cheng 已提交
75 76 77 78 79 80 81 82 83 84
  // 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;

  pPager->fd = open(pPager->dbFileName, O_RDWR | O_CREAT, 0755);
  if (pPager->fd < 0) {
H
more  
Hongze Cheng 已提交
85 86 87
    return -1;
  }

H
refact  
Hongze Cheng 已提交
88
  ret = tdbGnrtFileID(pPager->dbFileName, pPager->fid, false);
H
Hongze Cheng 已提交
89 90 91 92
  if (ret < 0) {
    return -1;
  }

H
refact  
Hongze Cheng 已提交
93
  pPager->jfd = -1;
H
Hongze Cheng 已提交
94
  pPager->pageSize = tdbPCacheGetPageSize(pCache);
H
more  
Hongze Cheng 已提交
95

H
refact  
Hongze Cheng 已提交
96
  *ppPager = pPager;
H
more  
Hongze Cheng 已提交
97 98 99
  return 0;
}

H
refact  
Hongze Cheng 已提交
100
int tdbPagerClose(SPager *pPager) {
H
more  
Hongze Cheng 已提交
101 102 103 104
  // TODO
  return 0;
}

H
refact  
Hongze Cheng 已提交
105
int tdbPagerOpenDB(SPager *pPager, SPgno *ppgno, bool toCreate) {
H
Hongze Cheng 已提交
106 107 108 109 110 111 112 113 114
  SPgno  pgno;
  SPage *pPage;
  int    ret;

  {
    // TODO: try to search the main DB to get the page number
    pgno = 0;
  }

H
more  
Hongze Cheng 已提交
115 116 117 118 119
  // if (pgno == 0 && toCreate) {
  //   ret = tdbPagerAllocPage(pPager, &pPage, &pgno);
  //   if (ret < 0) {
  //     return -1;
  //   }
H
Hongze Cheng 已提交
120

H
more  
Hongze Cheng 已提交
121
  //   // TODO: Need to zero the page
H
refact  
Hongze Cheng 已提交
122

H
more  
Hongze Cheng 已提交
123 124 125 126 127
  //   ret = tdbPagerWrite(pPager, pPage);
  //   if (ret < 0) {
  //     return -1;
  //   }
  // }
H
Hongze Cheng 已提交
128 129 130 131 132

  *ppgno = pgno;
  return 0;
}

H
refact  
Hongze Cheng 已提交
133
int tdbPagerWrite(SPager *pPager, SPage *pPage) {
H
more  
Hongze Cheng 已提交
134 135
  int ret;

H
refact  
Hongze Cheng 已提交
136 137
  if (pPager->inTran == 0) {
    ret = tdbPagerBegin(pPager);
H
more  
Hongze Cheng 已提交
138 139 140 141 142 143 144 145 146 147
    if (ret < 0) {
      return -1;
    }
  }

  if (pPage->isDirty == 0) {
    pPage->isDirty = 1;
    // TODO: add the page to the dirty list

    // TODO: write the page to the journal
H
Hongze Cheng 已提交
148 149
    if (1 /*actually load from the file*/) {
    }
H
more  
Hongze Cheng 已提交
150
  }
H
Hongze Cheng 已提交
151 152 153
  return 0;
}

H
refact  
Hongze Cheng 已提交
154 155
int tdbPagerBegin(SPager *pPager) {
  if (pPager->inTran) {
H
more  
Hongze Cheng 已提交
156 157
    return 0;
  }
H
Hongze Cheng 已提交
158 159

  // Open the journal
H
refact  
Hongze Cheng 已提交
160 161
  pPager->jfd = open(pPager->jFileName, O_RDWR | O_CREAT, 0755);
  if (pPager->jfd < 0) {
H
Hongze Cheng 已提交
162 163 164 165 166
    return -1;
  }

  // TODO: write the size of the file

H
refact  
Hongze Cheng 已提交
167
  pPager->inTran = 1;
H
Hongze Cheng 已提交
168

H
more  
Hongze Cheng 已提交
169 170 171
  return 0;
}

H
refact  
Hongze Cheng 已提交
172
int tdbPagerCommit(SPager *pPager) {
H
more  
Hongze Cheng 已提交
173 174 175 176
  // TODO
  return 0;
}

H
refact  
Hongze Cheng 已提交
177
static int tdbPagerReadPage(SPager *pPager, SPage *pPage) {
H
Hongze Cheng 已提交
178 179 180
  i64 offset;
  int ret;

H
refact  
Hongze Cheng 已提交
181
  ASSERT(memcmp(pPager->fid, pPage->pgid.fileid, TDB_FILE_ID_LEN) == 0);
H
Hongze Cheng 已提交
182

H
refact  
Hongze Cheng 已提交
183 184
  offset = (pPage->pgid.pgno - 1) * (i64)(pPager->pageSize);
  ret = tdbPRead(pPager->fd, pPage->pData, pPager->pageSize, offset);
H
Hongze Cheng 已提交
185 186 187 188 189
  if (ret < 0) {
    // TODO: handle error
    return -1;
  }
  return 0;
H
Hongze Cheng 已提交
190 191
}

H
refact  
Hongze Cheng 已提交
192 193
int tdbPagerGetPageSize(SPager *pPager) { return pPager->pageSize; }

H
Hongze Cheng 已提交
194
int tdbPagerFetchPage(SPager *pPager, SPgno pgno, SPage **ppPage, int (*initPage)(SPage *, void *), void *arg) {
H
more  
Hongze Cheng 已提交
195 196 197 198 199 200 201 202 203 204 205 206
  SPage *pPage;
  SPgid  pgid;
  int    ret;

  // Fetch a page container from the page cache
  memcpy(&pgid, pPager->fid, TDB_FILE_ID_LEN);
  pgid.pgno = pgno;
  pPage = tdbPCacheFetch(pPager->pCache, &pgid, 1);
  if (pPage == NULL) {
    return -1;
  }

H
Hongze Cheng 已提交
207 208 209 210 211
  // Initialize the page if need
  if (!TDB_PAGE_INITIALIZED(pPage)) {
    ret = tdbPagerInitPage(pPager, pPage, initPage, arg);
    if (ret < 0) {
      return -1;
H
more  
Hongze Cheng 已提交
212
    }
H
more  
Hongze Cheng 已提交
213 214
  }

H
Hongze Cheng 已提交
215 216 217
  ASSERT(TDB_PAGE_INITIALIZED(pPage));
  ASSERT(pPage->pPager == pPager);

H
more  
Hongze Cheng 已提交
218 219
  *ppPage = pPage;
  return 0;
H
refact  
Hongze Cheng 已提交
220 221
}

H
Hongze Cheng 已提交
222
int tdbPagerNewPage(SPager *pPager, SPgno *ppgno, SPage **ppPage, int (*initPage)(SPage *, void *), void *arg) {
H
more  
Hongze Cheng 已提交
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
  int    ret;
  SPage *pPage;
  SPgid  pgid;

  // Allocate a page number
  ret = tdbPagerAllocPage(pPager, ppgno);
  if (ret < 0) {
    return -1;
  }

  ASSERT(*ppgno != 0);

  // Fetch a page container from the page cache
  memcpy(&pgid, pPager->fid, TDB_FILE_ID_LEN);
  pgid.pgno = *ppgno;
  pPage = tdbPCacheFetch(pPager->pCache, &pgid, 1);
  if (pPage == NULL) {
    return -1;
  }

H
Hongze Cheng 已提交
243
  ASSERT(!TDB_PAGE_INITIALIZED(pPage));
H
more  
Hongze Cheng 已提交
244

H
Hongze Cheng 已提交
245 246 247 248 249
  // Initialize the page if need
  ret = tdbPagerInitPage(pPager, pPage, initPage, arg);
  if (ret < 0) {
    return -1;
  }
H
more  
Hongze Cheng 已提交
250

H
Hongze Cheng 已提交
251 252
  ASSERT(TDB_PAGE_INITIALIZED(pPage));
  ASSERT(pPage->pPager == pPager);
H
more  
Hongze Cheng 已提交
253

H
more  
Hongze Cheng 已提交
254 255 256 257
  *ppPage = pPage;
  return 0;
}

H
Hongze Cheng 已提交
258 259 260 261
void tdbPagerReturnPage(SPager *pPager, SPage *pPage) {
  tdbPCacheRelease(pPager->pCache, pPage);
}

H
more  
Hongze Cheng 已提交
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
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;
}

static int tdbPagerAllocPage(SPager *pPager, SPgno *ppgno) {
  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 已提交
293 294 295 296 297
  return 0;
}

static int tdbPagerInitPage(SPager *pPager, SPage *pPage, int (*initPage)(SPage *, void *), void *arg) {
  int ret;
H
Hongze Cheng 已提交
298
  int lcode;
H
Hongze Cheng 已提交
299
  int nLoops;
H
Hongze Cheng 已提交
300

H
Hongze Cheng 已提交
301 302
  lcode = TDB_TRY_LOCK_PAGE(pPage);
  if (lcode == P_LOCK_SUCC) {
H
Hongze Cheng 已提交
303 304 305 306 307 308 309 310 311 312 313 314 315 316
    if (TDB_PAGE_INITIALIZED(pPage)) {
      TDB_UNLOCK_PAGE(pPage);
      return 0;
    }

    ret = (*initPage)(pPage, arg);
    if (ret < 0) {
      TDB_UNLOCK_PAGE(pPage);
      return -1;
    }

    pPage->pPager = pPager;

    TDB_UNLOCK_PAGE(pPage);
H
Hongze Cheng 已提交
317
  } else if (lcode == P_LOCK_BUSY) {
H
Hongze Cheng 已提交
318 319 320 321 322 323 324 325 326
    nLoops = 0;
    for (;;) {
      if (TDB_PAGE_INITIALIZED(pPage)) break;
      nLoops++;
      if (nLoops > 1000) {
        sched_yield();
        nLoops = 0;
      }
    }
H
Hongze Cheng 已提交
327 328
  } else {
    return -1;
H
Hongze Cheng 已提交
329 330
  }

H
refact  
Hongze Cheng 已提交
331 332
  return 0;
}