tdbPage.c 3.7 KB
Newer Older
H
Hongze Cheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * 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 已提交
16 17
#include "tdbInt.h"

H
Hongze Cheng 已提交
18 19 20 21 22
typedef struct __attribute__((__packed__)) {
  u16 size;
  u16 nOffset;
} SFreeCell;

H
Hongze Cheng 已提交
23
static int tdbPageAllocate(SPage *pPage, int size, SCell **ppCell);
H
Hongze Cheng 已提交
24
static int tdbPageDefragment(SPage *pPage);
H
Hongze Cheng 已提交
25

H
Hongze Cheng 已提交
26
int tdbPageCreate(int pageSize, SPage **ppPage, void *(*xMalloc)(void *, size_t), void *arg) {
H
Hongze Cheng 已提交
27 28 29 30
  SPage *pPage;
  u8    *ptr;
  int    size;

H
Hongze Cheng 已提交
31 32
  ASSERT(TDB_IS_PGSIZE_VLD(pageSize));

H
Hongze Cheng 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45
  *ppPage = NULL;
  size = pageSize + sizeof(*pPage);

  ptr = (u8 *)((*xMalloc)(arg, size));
  if (pPage == NULL) {
    return -1;
  }

  memset(ptr, 0, size);
  pPage = (SPage *)(ptr + pageSize);

  pPage->pData = ptr;
  pPage->pageSize = pageSize;
H
Hongze Cheng 已提交
46 47
  if (pageSize < 65536) {
    pPage->szOffset = 2;
H
Hongze Cheng 已提交
48
    pPage->szPageHdr = sizeof(SPageHdr);
H
Hongze Cheng 已提交
49 50
  } else {
    pPage->szOffset = 3;
H
Hongze Cheng 已提交
51
    pPage->szPageHdr = sizeof(SLPageHdr);
H
Hongze Cheng 已提交
52
  }
H
Hongze Cheng 已提交
53
  TDB_INIT_PAGE_LOCK(pPage);
H
Hongze Cheng 已提交
54 55 56 57

  /* TODO */

  *ppPage = pPage;
H
Hongze Cheng 已提交
58 59 60
  return 0;
}

H
Hongze Cheng 已提交
61
int tdbPageDestroy(SPage *pPage, void (*xFree)(void *arg, void *ptr), void *arg) {
H
Hongze Cheng 已提交
62 63 64
  u8 *ptr;

  ptr = pPage->pData;
H
Hongze Cheng 已提交
65
  (*xFree)(arg, ptr);
H
Hongze Cheng 已提交
66

H
Hongze Cheng 已提交
67 68 69
  return 0;
}

H
Hongze Cheng 已提交
70
int tdbPageInsertCell(SPage *pPage, int idx, SCell *pCell, int szCell) {
H
Hongze Cheng 已提交
71 72 73
  int    ret;
  SCell *pTarget;

H
Hongze Cheng 已提交
74
  if (pPage->nOverflow || szCell + pPage->szOffset > pPage->nFree) {
H
Hongze Cheng 已提交
75
    // TODO: Page is full
H
Hongze Cheng 已提交
76 77 78 79 80
  } else {
    ret = tdbPageAllocate(pPage, szCell, &pTarget);
    if (ret < 0) {
      return -1;
    }
H
Hongze Cheng 已提交
81 82 83 84

    memcpy(pTarget, pCell, szCell);
    // TODO: memmove();
    // pPage->pPaggHdr->nCells++;
H
Hongze Cheng 已提交
85 86
  }

H
Hongze Cheng 已提交
87 88 89 90 91 92
  return 0;
}

int tdbPageDropCell(SPage *pPage, int idx) {
  // TODO
  return 0;
H
Hongze Cheng 已提交
93 94 95
}

static int tdbPageAllocate(SPage *pPage, int size, SCell **ppCell) {
H
Hongze Cheng 已提交
96 97 98
  SCell     *pCell;
  SFreeCell *pFreeCell;
  int        ret;
H
Hongze Cheng 已提交
99

H
Hongze Cheng 已提交
100
  ASSERT(pPage->nFree > size + pPage->szOffset);
H
Hongze Cheng 已提交
101

H
Hongze Cheng 已提交
102 103 104 105
  pCell = NULL;
  *ppCell = NULL;

  // 1. Try to allocate from the free space area
H
Hongze Cheng 已提交
106
  if (pPage->pFreeEnd - pPage->pFreeStart > size + pPage->szOffset) {
H
Hongze Cheng 已提交
107
    pPage->pFreeEnd -= size;
H
Hongze Cheng 已提交
108
    pPage->pFreeStart += pPage->szOffset;
H
Hongze Cheng 已提交
109 110 111 112

    pCell = pPage->pFreeEnd;
  }

H
Hongze Cheng 已提交
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
  // 2. Try to allocate from the page free list
  if (pCell == NULL && TDB_PAGE_FCELL(pPage)) {
    pCell = pPage->pData + TDB_PAGE_FCELL(pPage);
    for (;;) {
      pFreeCell = (SFreeCell *)pCell;

      if (pFreeCell->size >= size) {
        break;
      }

      if (pFreeCell->nOffset) {
        pCell = pPage->pData + pFreeCell->nOffset;
      } else {
        pCell = NULL;
        break;
      }

      continue;
    }
  }

  // 3. Try to dfragment
  if (pCell == NULL) {
    ret = tdbPageDefragment(pPage);
    if (ret < 0) {
      return -1;
    }

    ASSERT(pPage->pFreeEnd - pPage->pFreeStart > size + pPage->szOffset);
    ASSERT(pPage->nFree == pPage->pFreeEnd - pPage->pFreeStart);

    // Allocate from the free space area again
    pPage->pFreeEnd -= size;
    pPage->pFreeStart += pPage->szOffset;
    pCell = pPage->pFreeEnd;
  }

  ASSERT(pCell != NULL);

  pPage->nFree = pPage->nFree - size - pPage->szOffset;
H
Hongze Cheng 已提交
153
  *ppCell = pCell;
H
Hongze Cheng 已提交
154 155 156
  return 0;
}

H
Hongze Cheng 已提交
157
static int tdbPageFree(SPage *pPage, int idx, SCell *pCell, int size) {
H
Hongze Cheng 已提交
158 159
  // TODO
  return 0;
H
Hongze Cheng 已提交
160 161 162 163 164
}

static int tdbPageDefragment(SPage *pPage) {
  // TODO
  return 0;
H
Hongze Cheng 已提交
165
}