tdbPager.c 7.5 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
more  
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 29 30
  int      nDirty;
  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
refact  
Hongze Cheng 已提交
44
static int tdbPagerReadPage(SPager *pPager, SPage *pPage);
H
Hongze Cheng 已提交
45

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

H
refact  
Hongze Cheng 已提交
53
  *ppPager = NULL;
H
more  
Hongze Cheng 已提交
54 55

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

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

H
refact  
Hongze Cheng 已提交
84
  ret = tdbGnrtFileID(pPager->dbFileName, pPager->fid, false);
H
Hongze Cheng 已提交
85 86 87 88
  if (ret < 0) {
    return -1;
  }

H
refact  
Hongze Cheng 已提交
89
  pPager->jfd = -1;
H
Hongze Cheng 已提交
90
  pPager->pageSize = tdbPCacheGetPageSize(pCache);
H
more  
Hongze Cheng 已提交
91

H
refact  
Hongze Cheng 已提交
92
  *ppPager = pPager;
H
more  
Hongze Cheng 已提交
93 94 95
  return 0;
}

H
refact  
Hongze Cheng 已提交
96
int tdbPagerClose(SPager *pPager) {
H
more  
Hongze Cheng 已提交
97 98 99 100
  // TODO
  return 0;
}

H
refact  
Hongze Cheng 已提交
101
int tdbPagerOpenDB(SPager *pPager, SPgno *ppgno, bool toCreate) {
H
Hongze Cheng 已提交
102 103 104 105 106 107 108 109 110
  SPgno  pgno;
  SPage *pPage;
  int    ret;

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

H
more  
Hongze Cheng 已提交
111 112 113 114 115
  // if (pgno == 0 && toCreate) {
  //   ret = tdbPagerAllocPage(pPager, &pPage, &pgno);
  //   if (ret < 0) {
  //     return -1;
  //   }
H
Hongze Cheng 已提交
116

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

H
more  
Hongze Cheng 已提交
119 120 121 122 123
  //   ret = tdbPagerWrite(pPager, pPage);
  //   if (ret < 0) {
  //     return -1;
  //   }
  // }
H
Hongze Cheng 已提交
124 125 126 127 128

  *ppgno = pgno;
  return 0;
}

H
Hongze Cheng 已提交
129
SPage *tdbPagerGet(SPager *pPager, SPgno pgno, bool toLoad) {
H
refact  
Hongze Cheng 已提交
130 131
  SPgid  pgid;
  SPage *pPage;
H
Hongze Cheng 已提交
132
  int    ret;
H
more  
Hongze Cheng 已提交
133

H
refact  
Hongze Cheng 已提交
134
  memcpy(pgid.fileid, pPager->fid, TDB_FILE_ID_LEN);
H
more  
Hongze Cheng 已提交
135 136
  pgid.pgno = pgno;

H
Hongze Cheng 已提交
137
  // Get page frame from the SPCache
H
refact  
Hongze Cheng 已提交
138
  pPage = tdbPCacheFetch(pPager->pCache, &pgid, 1);
H
more  
Hongze Cheng 已提交
139
  if (pPage == NULL) {
H
more  
Hongze Cheng 已提交
140 141
    // TODO: handle error
    return NULL;
H
more  
Hongze Cheng 已提交
142
  }
H
refact  
Hongze Cheng 已提交
143
  tdbPCacheFetchFinish(pPager->pCache, pPage);
H
more  
Hongze Cheng 已提交
144

H
Hongze Cheng 已提交
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
  // Zero the page or load page content from backend
  // according to the options
  if (pPage->pPager == NULL || !toLoad) {
    if (!toLoad || pgno >= pPager->dbFileSize) {
      memset(pPage->pData, 0, pPager->pageSize);
    } else {
      ret = tdbPagerReadPage(pPager, pPage);
      if (ret < 0) {
        // TODO: Need to drop the page
        return NULL;
      }
    }

    if (pPage->pPager) {
      ASSERT(pPage->pPager == pPager);
    } else {
      pPage->pPager = pPager;
    }
  }

H
more  
Hongze Cheng 已提交
165
  return pPage;
H
more  
Hongze Cheng 已提交
166
}
H
Hongze Cheng 已提交
167

H
refact  
Hongze Cheng 已提交
168
int tdbPagerWrite(SPager *pPager, SPage *pPage) {
H
more  
Hongze Cheng 已提交
169 170
  int ret;

H
refact  
Hongze Cheng 已提交
171 172
  if (pPager->inTran == 0) {
    ret = tdbPagerBegin(pPager);
H
more  
Hongze Cheng 已提交
173 174 175 176 177 178 179 180 181 182
    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 已提交
183 184
    if (1 /*actually load from the file*/) {
    }
H
more  
Hongze Cheng 已提交
185
  }
H
Hongze Cheng 已提交
186 187 188
  return 0;
}

H
more  
Hongze Cheng 已提交
189 190 191
// int tdbPagerAllocPage(SPager *pPager, SPage **ppPage, SPgno *ppgno) {
//   SPage *pPage;
//   SPgno  pgno;
H
Hongze Cheng 已提交
192

H
more  
Hongze Cheng 已提交
193 194 195 196 197 198 199 200
//   if (1 /*TODO: no free page*/) {
//     pgno = ++pPager->dbFileSize;
//     pPage = tdbPagerGet(pPager, pgno, false);
//     ASSERT(pPage != NULL);
//   } else {
//     /* TODO: allocate from the free list */
//     ASSERT(0);
//   }
H
Hongze Cheng 已提交
201

H
more  
Hongze Cheng 已提交
202 203 204 205
//   *ppPage = pPage;
//   *ppgno = pgno;
//   return 0;
// }
H
Hongze Cheng 已提交
206

H
refact  
Hongze Cheng 已提交
207 208
int tdbPagerBegin(SPager *pPager) {
  if (pPager->inTran) {
H
more  
Hongze Cheng 已提交
209 210
    return 0;
  }
H
Hongze Cheng 已提交
211 212

  // Open the journal
H
refact  
Hongze Cheng 已提交
213 214
  pPager->jfd = open(pPager->jFileName, O_RDWR | O_CREAT, 0755);
  if (pPager->jfd < 0) {
H
Hongze Cheng 已提交
215 216 217 218 219
    return -1;
  }

  // TODO: write the size of the file

H
refact  
Hongze Cheng 已提交
220
  pPager->inTran = 1;
H
Hongze Cheng 已提交
221

H
more  
Hongze Cheng 已提交
222 223 224
  return 0;
}

H
refact  
Hongze Cheng 已提交
225
int tdbPagerCommit(SPager *pPager) {
H
more  
Hongze Cheng 已提交
226 227 228 229
  // TODO
  return 0;
}

H
refact  
Hongze Cheng 已提交
230
static int tdbPagerReadPage(SPager *pPager, SPage *pPage) {
H
Hongze Cheng 已提交
231 232 233
  i64 offset;
  int ret;

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

H
refact  
Hongze Cheng 已提交
236 237
  offset = (pPage->pgid.pgno - 1) * (i64)(pPager->pageSize);
  ret = tdbPRead(pPager->fd, pPage->pData, pPager->pageSize, offset);
H
Hongze Cheng 已提交
238 239 240 241 242
  if (ret < 0) {
    // TODO: handle error
    return -1;
  }
  return 0;
H
Hongze Cheng 已提交
243 244
}

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

H
more  
Hongze Cheng 已提交
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
int tdbPagerFetchPage(SPager *pPager, SPgno pgno, SPage **ppPage) {
  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;
  }

  if (pPage->pPager == NULL) {
    ASSERT(pgno < pPager->dbOrigSize);

H
more  
Hongze Cheng 已提交
263 264 265 266 267 268 269
    // tdbWLockPage(pPage);

    if (pPage->pPager == NULL) {
      ret = tdbPagerReadPage(pPager, pPage);
      if (ret < 0) {
        return -1;
      }
H
refact  
Hongze Cheng 已提交
270

H
more  
Hongze Cheng 已提交
271 272 273 274
      // ret = (*initPage)(pPage);
      // if (ret < 0) {
      //   return -1;
      // }
H
more  
Hongze Cheng 已提交
275

H
more  
Hongze Cheng 已提交
276 277 278 279
      pPage->pPager = pPager;
    }

    // tdbWUnlockPage(pPage);
H
more  
Hongze Cheng 已提交
280 281 282 283 284 285
  } else {
    ASSERT(pPage->pPager == pPager);
  }

  *ppPage = pPage;
  return 0;
H
refact  
Hongze Cheng 已提交
286 287
}

H
more  
Hongze Cheng 已提交
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
int tdbPagerNewPage(SPager *pPager, SPgno *ppgno, SPage **ppPage) {
  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;
  }

  ASSERT(pPage->pPager == NULL);

H
more  
Hongze Cheng 已提交
311 312 313 314
  // TODO: a race condition problem may occur here

  // tdbWLockPage(pPage);

H
more  
Hongze Cheng 已提交
315 316 317
  // TODO: zero init the new page
  // (*initNewPage)(pPage, arg);

H
more  
Hongze Cheng 已提交
318 319 320 321 322
  pPage->pPager = NULL;

  // tdbWunlockPage(pPage);


H
more  
Hongze Cheng 已提交
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
  *ppPage = pPage;
  return 0;
}

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
refact  
Hongze Cheng 已提交
358 359
  return 0;
}