tdbPage.c 4.3 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
  SCell     *pCell;
  SFreeCell *pFreeCell;
H
Hongze Cheng 已提交
98
  u8        *pOffset;
H
Hongze Cheng 已提交
99
  int        ret;
H
Hongze Cheng 已提交
100

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

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

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

H
Hongze Cheng 已提交
113
  // 2. Try to allocate from the page free list
H
Hongze Cheng 已提交
114
  if ((pCell == NULL) && (pPage->pFreeEnd - pPage->pFreeStart >= pPage->szOffset) && TDB_PAGE_FCELL(pPage)) {
H
Hongze Cheng 已提交
115
    pCell = pPage->pData + TDB_PAGE_FCELL(pPage);
H
Hongze Cheng 已提交
116 117
    // TODO: pOffset = TDB_PAGE_FCELL(pPage);

H
Hongze Cheng 已提交
118 119 120 121
    for (;;) {
      pFreeCell = (SFreeCell *)pCell;

      if (pFreeCell->size >= size) {
H
Hongze Cheng 已提交
122 123 124 125 126 127 128 129
        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 已提交
130 131 132 133 134
        break;
      }

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

H
Hongze Cheng 已提交
168
static int tdbPageFree(SPage *pPage, int idx, SCell *pCell, int size) {
H
Hongze Cheng 已提交
169 170
  // TODO
  return 0;
H
Hongze Cheng 已提交
171 172 173 174 175
}

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