tdbPage.c 4.4 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 24 25 26 27
typedef struct __attribute__((__packed__)) {
  u8 size[3];
  u8 nOffset[3];
} SFreeCellL;

H
Hongze Cheng 已提交
28
static int tdbPageAllocate(SPage *pPage, int size, SCell **ppCell);
H
Hongze Cheng 已提交
29
static int tdbPageDefragment(SPage *pPage);
H
Hongze Cheng 已提交
30

H
Hongze Cheng 已提交
31
int tdbPageCreate(int pageSize, SPage **ppPage, void *(*xMalloc)(void *, size_t), void *arg) {
H
Hongze Cheng 已提交
32 33 34 35
  SPage *pPage;
  u8    *ptr;
  int    size;

H
Hongze Cheng 已提交
36 37
  ASSERT(TDB_IS_PGSIZE_VLD(pageSize));

H
Hongze Cheng 已提交
38 39 40 41 42 43 44 45 46 47 48 49 50
  *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 已提交
51 52
  if (pageSize < 65536) {
    pPage->szOffset = 2;
H
Hongze Cheng 已提交
53
    pPage->szPageHdr = sizeof(SPageHdr);
H
Hongze Cheng 已提交
54
    pPage->szFreeCell = sizeof(SFreeCell);
H
Hongze Cheng 已提交
55 56
  } else {
    pPage->szOffset = 3;
H
Hongze Cheng 已提交
57
    pPage->szPageHdr = sizeof(SLPageHdr);
H
Hongze Cheng 已提交
58
    pPage->szFreeCell = sizeof(SFreeCellL);
H
Hongze Cheng 已提交
59
  }
H
Hongze Cheng 已提交
60
  TDB_INIT_PAGE_LOCK(pPage);
H
Hongze Cheng 已提交
61 62 63 64

  /* TODO */

  *ppPage = pPage;
H
Hongze Cheng 已提交
65 66 67
  return 0;
}

H
Hongze Cheng 已提交
68
int tdbPageDestroy(SPage *pPage, void (*xFree)(void *arg, void *ptr), void *arg) {
H
Hongze Cheng 已提交
69 70 71
  u8 *ptr;

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

H
Hongze Cheng 已提交
74 75 76
  return 0;
}

H
Hongze Cheng 已提交
77
int tdbPageInsertCell(SPage *pPage, int idx, SCell *pCell, int szCell) {
H
Hongze Cheng 已提交
78 79 80
  int    ret;
  SCell *pTarget;

H
Hongze Cheng 已提交
81
  if (pPage->nOverflow || szCell + pPage->szOffset > pPage->nFree) {
H
Hongze Cheng 已提交
82
    // TODO: Page is full
H
Hongze Cheng 已提交
83 84 85 86 87
  } else {
    ret = tdbPageAllocate(pPage, szCell, &pTarget);
    if (ret < 0) {
      return -1;
    }
H
Hongze Cheng 已提交
88 89 90 91

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

H
Hongze Cheng 已提交
94 95 96 97 98 99
  return 0;
}

int tdbPageDropCell(SPage *pPage, int idx) {
  // TODO
  return 0;
H
Hongze Cheng 已提交
100 101 102
}

static int tdbPageAllocate(SPage *pPage, int size, SCell **ppCell) {
H
Hongze Cheng 已提交
103 104
  SCell     *pCell;
  SFreeCell *pFreeCell;
H
Hongze Cheng 已提交
105
  u8        *pOffset;
H
Hongze Cheng 已提交
106
  int        ret;
H
Hongze Cheng 已提交
107

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

H
Hongze Cheng 已提交
110 111 112 113
  pCell = NULL;
  *ppCell = NULL;

  // 1. Try to allocate from the free space area
H
Hongze Cheng 已提交
114
  if (pPage->pFreeEnd - pPage->pFreeStart > size + pPage->szOffset) {
H
Hongze Cheng 已提交
115
    pPage->pFreeEnd -= size;
H
Hongze Cheng 已提交
116
    pPage->pFreeStart += pPage->szOffset;
H
Hongze Cheng 已提交
117 118 119
    pCell = pPage->pFreeEnd;
  }

H
Hongze Cheng 已提交
120
  // 2. Try to allocate from the page free list
H
Hongze Cheng 已提交
121
  if ((pCell == NULL) && (pPage->pFreeEnd - pPage->pFreeStart >= pPage->szOffset) && TDB_PAGE_FCELL(pPage)) {
H
Hongze Cheng 已提交
122
    pCell = pPage->pData + TDB_PAGE_FCELL(pPage);
H
Hongze Cheng 已提交
123 124
    // TODO: pOffset = TDB_PAGE_FCELL(pPage);

H
Hongze Cheng 已提交
125 126 127 128
    for (;;) {
      pFreeCell = (SFreeCell *)pCell;

      if (pFreeCell->size >= size) {
H
Hongze Cheng 已提交
129 130 131 132 133 134 135 136
        if (pFreeCell->size - size >= 4 /*TODO*/) {
          ((SFreeCell *)(pCell + size))[0].size = pFreeCell->size - size;
          ((SFreeCell *)(pCell + size))[0].nOffset = pFreeCell->nOffset;
          // *(u16 *)pOffset =  pCell + size - pPage->pData;
        } else {
          TDB_PAGE_NFREE_SET(pPage, TDB_PAGE_NFREE(pPage) + pFreeCell->size - size);
          // *(u16 *)pOffset = pFreeCell->nOffset;
        }
H
Hongze Cheng 已提交
137 138 139 140 141
        break;
      }

      if (pFreeCell->nOffset) {
        pCell = pPage->pData + pFreeCell->nOffset;
H
Hongze Cheng 已提交
142
        // TODO: pOffset = &(pFreeCell->nOffset);
H
Hongze Cheng 已提交
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
      } 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 已提交
171
  *ppCell = pCell;
H
Hongze Cheng 已提交
172 173 174
  return 0;
}

H
Hongze Cheng 已提交
175
static int tdbPageFree(SPage *pPage, int idx, SCell *pCell, int size) {
H
Hongze Cheng 已提交
176 177
  // TODO
  return 0;
H
Hongze Cheng 已提交
178 179 180 181 182
}

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