tdbPage.c 7.8 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
typedef struct __attribute__((__packed__)) {
H
Hongze Cheng 已提交
19
  u8 szCell[2];
H
Hongze Cheng 已提交
20
  u8 nxOffset[2];
H
Hongze Cheng 已提交
21 22
} SFreeCell;

H
Hongze Cheng 已提交
23
typedef struct __attribute__((__packed__)) {
H
Hongze Cheng 已提交
24
  u8 szCell[3];
H
Hongze Cheng 已提交
25
  u8 nxOffset[3];
H
Hongze Cheng 已提交
26 27
} SFreeCellL;

H
Hongze Cheng 已提交
28
/* For small page */
H
Hongze Cheng 已提交
29
#define TDB_SPAGE_FREE_CELL_SIZE_PTR(PCELL)     (((SFreeCell *)(PCELL))->szCell)
H
Hongze Cheng 已提交
30
#define TDB_SPAGE_FREE_CELL_NXOFFSET_PTR(PCELL) (((SFreeCell *)(PCELL))->nxOffset)
H
Hongze Cheng 已提交
31

H
Hongze Cheng 已提交
32 33 34 35 36
#define TDB_SPAGE_FREE_CELL_SIZE(PCELL)     ((u16 *)TDB_SPAGE_FREE_CELL_SIZE_PTR(PCELL))[0]
#define TDB_SPAGE_FREE_CELL_NXOFFSET(PCELL) ((u16 *)TDB_SPAGE_FREE_CELL_NXOFFSET_PTR(PCELL))[0]

#define TDB_SPAGE_FREE_CELL_SIZE_SET(PCELL, SIZE)       (TDB_SPAGE_FREE_CELL_SIZE(PCELL) = (SIZE))
#define TDB_SPAGE_FREE_CELL_NXOFFSET_SET(PCELL, OFFSET) (TDB_SPAGE_FREE_CELL_NXOFFSET(PCELL) = (OFFSET))
H
Hongze Cheng 已提交
37 38

/* For large page */
H
Hongze Cheng 已提交
39
#define TDB_LPAGE_FREE_CELL_SIZE_PTR(PCELL)     (((SFreeCellL *)(PCELL))->szCell)
H
Hongze Cheng 已提交
40 41 42 43
#define TDB_LPAGE_FREE_CELL_NXOFFSET_PTR(PCELL) (((SFreeCellL *)(PCELL))->nxOffset)

#define TDB_LPAGE_FREE_CELL_SIZE(PCELL)     TDB_GET_U24(TDB_LPAGE_FREE_CELL_SIZE_PTR(PCELL))
#define TDB_LPAGE_FREE_CELL_NXOFFSET(PCELL) TDB_GET_U24(TDB_LPAGE_FREE_CELL_NXOFFSET_PTR(PCELL))
H
Hongze Cheng 已提交
44

H
Hongze Cheng 已提交
45 46
#define TDB_LPAGE_FREE_CELL_SIZE_SET(PCELL, SIZE)       TDB_PUT_U24(TDB_LPAGE_FREE_CELL_SIZE_PTR(PCELL), SIZE)
#define TDB_LPAGE_FREE_CELL_NXOFFSET_SET(PCELL, OFFSET) TDB_PUT_U24(TDB_LPAGE_FREE_CELL_NXOFFSET_PTR(PCELL), OFFSET)
H
Hongze Cheng 已提交
47 48

/* For page */
H
Hongze Cheng 已提交
49 50 51 52 53
#define TDB_PAGE_FREE_CELL_SIZE_PTR(PPAGE, PCELL) \
  (TDB_IS_LARGE_PAGE(pPage) ? TDB_LPAGE_FREE_CELL_SIZE_PTR(PCELL) : TDB_SPAGE_FREE_CELL_SIZE_PTR(PCELL))
#define TDB_PAGE_FREE_CELL_NXOFFSET_PTR(PPAGE, PCELL) \
  (TDB_IS_LARGE_PAGE(pPage) ? TDB_LPAGE_FREE_CELL_NXOFFSET_PTR(PCELL) : TDB_SPAGE_FREE_CELL_NXOFFSET_PTR(PCELL))

H
Hongze Cheng 已提交
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
#define TDB_PAGE_FREE_CELL_SIZE(PPAGE, PCELL) \
  (TDB_IS_LARGE_PAGE(pPage) ? TDB_LPAGE_FREE_CELL_SIZE(PCELL) : TDB_SPAGE_FREE_CELL_SIZE(PCELL))
#define TDB_PAGE_FREE_CELL_NXOFFSET(PPAGE, PCELL) \
  (TDB_IS_LARGE_PAGE(pPage) ? TDB_LPAGE_FREE_CELL_NXOFFSET(PCELL) : TDB_SPAGE_FREE_CELL_NXOFFSET(PCELL))

#define TDB_PAGE_FREE_CELL_SIZE_SET(PPAGE, PCELL, SIZE) \
  do {                                                  \
    if (TDB_IS_LARGE_PAGE(PPAGE)) {                     \
      TDB_LPAGE_FREE_CELL_SIZE_SET(PCELL, SIZE);        \
    } else {                                            \
      TDB_SPAGE_FREE_CELL_SIZE_SET(PCELL, SIZE);        \
    }                                                   \
  } while (0)
#define TDB_PAGE_FREE_CELL_NXOFFSET_SET(PPAGE, PCELL, OFFSET) \
  do {                                                        \
    if (TDB_IS_LARGE_PAGE(PPAGE)) {                           \
      TDB_LPAGE_FREE_CELL_NXOFFSET_SET(PCELL, OFFSET);        \
    } else {                                                  \
      TDB_SPAGE_FREE_CELL_NXOFFSET_SET(PCELL, OFFSET);        \
    }                                                         \
  } while (0)
H
Hongze Cheng 已提交
75

H
Hongze Cheng 已提交
76
static int tdbPageAllocate(SPage *pPage, int size, SCell **ppCell);
H
Hongze Cheng 已提交
77
static int tdbPageDefragment(SPage *pPage);
H
Hongze Cheng 已提交
78

H
Hongze Cheng 已提交
79
int tdbPageCreate(int pageSize, SPage **ppPage, void *(*xMalloc)(void *, size_t), void *arg) {
H
Hongze Cheng 已提交
80 81 82 83
  SPage *pPage;
  u8    *ptr;
  int    size;

H
Hongze Cheng 已提交
84 85
  ASSERT(TDB_IS_PGSIZE_VLD(pageSize));

H
Hongze Cheng 已提交
86 87 88 89 90 91 92 93 94 95 96 97 98
  *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 已提交
99 100
  if (pageSize < 65536) {
    pPage->szOffset = 2;
H
Hongze Cheng 已提交
101
    pPage->szPageHdr = sizeof(SPageHdr);
H
Hongze Cheng 已提交
102
    pPage->szFreeCell = sizeof(SFreeCell);
H
Hongze Cheng 已提交
103 104
  } else {
    pPage->szOffset = 3;
H
Hongze Cheng 已提交
105
    pPage->szPageHdr = sizeof(SPageHdrL);
H
Hongze Cheng 已提交
106
    pPage->szFreeCell = sizeof(SFreeCellL);
H
Hongze Cheng 已提交
107
  }
H
Hongze Cheng 已提交
108
  TDB_INIT_PAGE_LOCK(pPage);
H
Hongze Cheng 已提交
109 110 111 112

  /* TODO */

  *ppPage = pPage;
H
Hongze Cheng 已提交
113 114 115
  return 0;
}

H
Hongze Cheng 已提交
116
int tdbPageDestroy(SPage *pPage, void (*xFree)(void *arg, void *ptr), void *arg) {
H
Hongze Cheng 已提交
117 118 119
  u8 *ptr;

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

H
Hongze Cheng 已提交
122 123 124
  return 0;
}

H
Hongze Cheng 已提交
125
int tdbPageInsertCell(SPage *pPage, int idx, SCell *pCell, int szCell) {
H
Hongze Cheng 已提交
126 127
  int    ret;
  SCell *pTarget;
H
Hongze Cheng 已提交
128
  u8    *pTmp;
H
Hongze Cheng 已提交
129

H
Hongze Cheng 已提交
130
  if (pPage->nOverflow || szCell + pPage->szOffset > pPage->nFree) {
H
Hongze Cheng 已提交
131
    // TODO: Page is full
H
Hongze Cheng 已提交
132
    ASSERT(0);
H
Hongze Cheng 已提交
133 134 135 136 137
  } else {
    ret = tdbPageAllocate(pPage, szCell, &pTarget);
    if (ret < 0) {
      return -1;
    }
H
Hongze Cheng 已提交
138 139

    memcpy(pTarget, pCell, szCell);
H
Hongze Cheng 已提交
140
    pTmp = pPage->pCellIdx + idx * pPage->szOffset;
H
Hongze Cheng 已提交
141
    memmove(pTmp + pPage->szOffset, pTmp, pPage->pFreeStart - pTmp - pPage->szOffset);
H
Hongze Cheng 已提交
142
    TDB_PAGE_CELL_OFFSET_AT_SET(pPage, idx, pTarget - pPage->pData);
H
Hongze Cheng 已提交
143
    TDB_PAGE_NCELLS_SET(pPage, TDB_PAGE_NCELLS(pPage) + 1);
H
Hongze Cheng 已提交
144 145
  }

H
Hongze Cheng 已提交
146 147 148 149 150 151
  return 0;
}

int tdbPageDropCell(SPage *pPage, int idx) {
  // TODO
  return 0;
H
Hongze Cheng 已提交
152 153 154
}

static int tdbPageAllocate(SPage *pPage, int size, SCell **ppCell) {
H
Hongze Cheng 已提交
155 156
  SCell     *pCell;
  SFreeCell *pFreeCell;
H
Hongze Cheng 已提交
157
  u8        *pOffset;
H
Hongze Cheng 已提交
158
  int        ret;
H
Hongze Cheng 已提交
159

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

H
Hongze Cheng 已提交
162 163 164 165
  pCell = NULL;
  *ppCell = NULL;

  // 1. Try to allocate from the free space area
H
Hongze Cheng 已提交
166
  if (pPage->pFreeEnd - pPage->pFreeStart > size + pPage->szOffset) {
H
Hongze Cheng 已提交
167
    pPage->pFreeEnd -= size;
H
Hongze Cheng 已提交
168
    pPage->pFreeStart += pPage->szOffset;
H
Hongze Cheng 已提交
169 170 171
    pCell = pPage->pFreeEnd;
  }

H
Hongze Cheng 已提交
172
  // 2. Try to allocate from the page free list
H
Hongze Cheng 已提交
173
  if ((pCell == NULL) && (pPage->pFreeEnd - pPage->pFreeStart >= pPage->szOffset) && TDB_PAGE_FCELL(pPage)) {
H
Hongze Cheng 已提交
174 175 176
    int szCell;
    int nxOffset;

H
Hongze Cheng 已提交
177
    pCell = pPage->pData + TDB_PAGE_FCELL(pPage);
H
Hongze Cheng 已提交
178
    pOffset = TDB_IS_LARGE_PAGE(pPage) ? ((SPageHdrL *)(pPage->pPageHdr))[0].fCell
H
Hongze Cheng 已提交
179
                                       : (u8 *)&(((SPageHdr *)(pPage->pPageHdr))[0].fCell);
H
Hongze Cheng 已提交
180 181
    szCell = TDB_PAGE_FREE_CELL_SIZE(pPage, pCell);
    nxOffset = TDB_PAGE_FREE_CELL_NXOFFSET(pPage, pCell);
H
Hongze Cheng 已提交
182 183

    for (;;) {
H
Hongze Cheng 已提交
184 185 186 187 188 189 190 191
      // Find a cell
      if (szCell >= size) {
        if (szCell - size >= pPage->szFreeCell) {
          SCell *pTmpCell = pCell + size;

          TDB_PAGE_FREE_CELL_SIZE_SET(pPage, pTmpCell, szCell - size);
          TDB_PAGE_FREE_CELL_NXOFFSET_SET(pPage, pTmpCell, nxOffset);
          // TODO: *pOffset = pTmpCell - pPage->pData;
H
Hongze Cheng 已提交
192
        } else {
H
Hongze Cheng 已提交
193 194
          TDB_PAGE_NFREE_SET(pPage, TDB_PAGE_NFREE(pPage) + szCell - size);
          // TODO: *pOffset = nxOffset;
H
Hongze Cheng 已提交
195
        }
H
Hongze Cheng 已提交
196 197 198
        break;
      }

H
Hongze Cheng 已提交
199 200 201 202 203 204 205
      // Not find a cell yet
      if (nxOffset > 0) {
        pCell = pPage->pData + nxOffset;
        pOffset = TDB_PAGE_FREE_CELL_NXOFFSET_PTR(pPage, pCell);
        szCell = TDB_PAGE_FREE_CELL_SIZE(pPage, pCell);
        nxOffset = TDB_PAGE_FREE_CELL_NXOFFSET(pPage, pCell);
        continue;
H
Hongze Cheng 已提交
206 207 208 209 210
      } else {
        pCell = NULL;
        break;
      }
    }
H
Hongze Cheng 已提交
211 212

    if (pCell) {
H
Hongze Cheng 已提交
213
      pPage->pFreeStart = pPage->pFreeStart + pPage->szOffset;
H
Hongze Cheng 已提交
214
    }
H
Hongze Cheng 已提交
215 216
  }

H
Hongze Cheng 已提交
217
  // 3. Try to dfragment and allocate again
H
Hongze Cheng 已提交
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
  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 已提交
236
  *ppCell = pCell;
H
Hongze Cheng 已提交
237 238 239
  return 0;
}

H
Hongze Cheng 已提交
240
static int tdbPageFree(SPage *pPage, int idx, SCell *pCell, int size) {
H
Hongze Cheng 已提交
241 242
  // TODO
  return 0;
H
Hongze Cheng 已提交
243 244 245 246
}

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