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
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
static int tdbPagerAllocPage(SPager *pPager, SPgno *ppgno);
H
Hongze Cheng 已提交
46

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

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

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

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

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

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

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

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

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

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

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

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

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

  *ppgno = pgno;
  return 0;
}

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

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

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

H
Hongze Cheng 已提交
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
  // 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 已提交
166
  return pPage;
H
more  
Hongze Cheng 已提交
167
}
H
Hongze Cheng 已提交
168

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

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

H
refact  
Hongze Cheng 已提交
190 191
int tdbPagerBegin(SPager *pPager) {
  if (pPager->inTran) {
H
more  
Hongze Cheng 已提交
192 193
    return 0;
  }
H
Hongze Cheng 已提交
194 195

  // Open the journal
H
refact  
Hongze Cheng 已提交
196 197
  pPager->jfd = open(pPager->jFileName, O_RDWR | O_CREAT, 0755);
  if (pPager->jfd < 0) {
H
Hongze Cheng 已提交
198 199 200 201 202
    return -1;
  }

  // TODO: write the size of the file

H
refact  
Hongze Cheng 已提交
203
  pPager->inTran = 1;
H
Hongze Cheng 已提交
204

H
more  
Hongze Cheng 已提交
205 206 207
  return 0;
}

H
refact  
Hongze Cheng 已提交
208
int tdbPagerCommit(SPager *pPager) {
H
more  
Hongze Cheng 已提交
209 210 211 212
  // TODO
  return 0;
}

H
refact  
Hongze Cheng 已提交
213
static int tdbPagerReadPage(SPager *pPager, SPage *pPage) {
H
Hongze Cheng 已提交
214 215 216
  i64 offset;
  int ret;

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

H
refact  
Hongze Cheng 已提交
219 220
  offset = (pPage->pgid.pgno - 1) * (i64)(pPager->pageSize);
  ret = tdbPRead(pPager->fd, pPage->pData, pPager->pageSize, offset);
H
Hongze Cheng 已提交
221 222 223 224 225
  if (ret < 0) {
    // TODO: handle error
    return -1;
  }
  return 0;
H
Hongze Cheng 已提交
226 227
}

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

H
more  
Hongze Cheng 已提交
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
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 已提交
246 247 248 249 250 251 252
    // tdbWLockPage(pPage);

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

H
more  
Hongze Cheng 已提交
254 255 256 257
      // ret = (*initPage)(pPage);
      // if (ret < 0) {
      //   return -1;
      // }
H
more  
Hongze Cheng 已提交
258

H
more  
Hongze Cheng 已提交
259 260 261 262
      pPage->pPager = pPager;
    }

    // tdbWUnlockPage(pPage);
H
more  
Hongze Cheng 已提交
263 264 265 266 267 268
  } else {
    ASSERT(pPage->pPager == pPager);
  }

  *ppPage = pPage;
  return 0;
H
refact  
Hongze Cheng 已提交
269 270
}

H
more  
Hongze Cheng 已提交
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
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 已提交
294 295 296 297
  // TODO: a race condition problem may occur here

  // tdbWLockPage(pPage);

H
more  
Hongze Cheng 已提交
298 299 300
  // TODO: zero init the new page
  // (*initNewPage)(pPage, arg);

H
more  
Hongze Cheng 已提交
301 302 303 304
  pPage->pPager = NULL;

  // tdbWunlockPage(pPage);

H
more  
Hongze Cheng 已提交
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
  *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 已提交
340 341
  return 0;
}