tdbBtree.c 8.5 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
Hongze Cheng 已提交
18 19 20 21 22
#define TDB_BTREE_ROOT 0x1
#define TDB_BTREE_LEAF 0x2

#define TDB_BTREE_PAGE_IS_ROOT(flags) TDB_FLAG_HAS(flags, TDB_BTREE_ROOT)
#define TDB_BTREE_PAGE_IS_LEAF(flags) TDB_FLAG_HAS(flags, TDB_BTREE_LEAF)
H
Hongze Cheng 已提交
23 24 25
#define TDB_BTREE_ASSERT_FLAG(flags)                                                 \
  ASSERT(TDB_FLAG_IS(flags, TDB_BTREE_ROOT) || TDB_FLAG_IS(flags, TDB_BTREE_LEAF) || \
         TDB_FLAG_IS(flags, TDB_BTREE_ROOT | TDB_BTREE_LEAF) || TDB_FLAG_IS(flags, 0))
H
Hongze Cheng 已提交
26

H
Hongze Cheng 已提交
27
struct SBTree {
H
more  
Hongze Cheng 已提交
28 29 30
  SPgno          root;
  int            keyLen;
  int            valLen;
H
refact  
Hongze Cheng 已提交
31
  SPager *       pPager;
H
more  
Hongze Cheng 已提交
32
  FKeyComparator kcmpr;
H
more  
Hongze Cheng 已提交
33
  u8             fanout;
H
Hongze Cheng 已提交
34
  int            pageSize;
H
more  
Hongze Cheng 已提交
35 36 37 38
  int            maxLocal;
  int            minLocal;
  int            maxLeaf;
  int            minLeaf;
H
Hongze Cheng 已提交
39 40
};

H
more  
Hongze Cheng 已提交
41 42 43 44 45
typedef struct SFreeCell {
  u16 size;
  u16 next;
} SFreeCell;

H
Hongze Cheng 已提交
46 47 48 49 50
typedef struct {
  u16     flags;
  SBTree *pBt;
} SBtreeZeroPageArg;

H
Hongze Cheng 已提交
51
static int tdbBtCursorMoveTo(SBtCursor *pCur, const void *pKey, int kLen);
H
more  
Hongze Cheng 已提交
52
static int tdbEncodeLength(u8 *pBuf, uint32_t len);
H
more  
Hongze Cheng 已提交
53
static int tdbBtCursorMoveToRoot(SBtCursor *pCur);
H
more  
Hongze Cheng 已提交
54
static int tdbCompareKeyAndCell(const void *pKey, int kLen, const void *pCell);
H
Hongze Cheng 已提交
55
static int tdbDefaultKeyCmprFn(const void *pKey1, int keyLen1, const void *pKey2, int keyLen2);
H
Hongze Cheng 已提交
56
static int tdbBtreeOpenImpl(SBTree *pBt);
H
Hongze Cheng 已提交
57 58
static int tdbBtreeZeroPage(SPage *pPage, void *arg);
static int tdbBtreeInitPage(SPage *pPage, void *arg);
H
Hongze Cheng 已提交
59

H
Hongze Cheng 已提交
60
int tdbBtreeOpen(int keyLen, int valLen, SPager *pPager, FKeyComparator kcmpr, SBTree **ppBt) {
H
Hongze Cheng 已提交
61
  SBTree *pBt;
H
Hongze Cheng 已提交
62
  int     ret;
H
more  
Hongze Cheng 已提交
63

H
Hongze Cheng 已提交
64
  *ppBt = NULL;
H
Hongze Cheng 已提交
65 66 67 68 69 70 71 72 73 74

  pBt = (SBTree *)calloc(1, sizeof(*pBt));
  if (pBt == NULL) {
    return -1;
  }

  // pBt->keyLen
  pBt->keyLen = keyLen;
  // pBt->valLen
  pBt->valLen = valLen;
H
refact  
Hongze Cheng 已提交
75 76
  // pBt->pPager
  pBt->pPager = pPager;
H
Hongze Cheng 已提交
77 78
  // pBt->kcmpr
  pBt->kcmpr = kcmpr ? kcmpr : tdbDefaultKeyCmprFn;
H
more  
Hongze Cheng 已提交
79 80 81 82 83 84 85
  // pBt->fanout
  if (keyLen == TDB_VARIANT_LEN) {
    pBt->fanout = TDB_DEFAULT_FANOUT;
  } else {
    ASSERT(0);
    // TODO: pBt->fanout = 0;
  }
H
Hongze Cheng 已提交
86 87 88 89 90 91 92 93 94 95
  // pBt->pageSize
  pBt->pageSize = tdbPagerGetPageSize(pPager);
  // pBt->maxLocal
  pBt->maxLocal = (pBt->pageSize - sizeof(SPageHdr)) / pBt->fanout;
  // pBt->minLocal
  pBt->minLocal = (pBt->pageSize - sizeof(SPageHdr)) / pBt->fanout / 2;
  // pBt->maxLeaf
  pBt->maxLeaf = pBt->pageSize - sizeof(SPageHdr);
  // pBt->minLeaf
  pBt->minLeaf = pBt->minLocal;
H
Hongze Cheng 已提交
96

H
Hongze Cheng 已提交
97 98 99 100 101 102 103
  // TODO: pBt->root
  ret = tdbBtreeOpenImpl(pBt);
  if (ret < 0) {
    free(pBt);
    return -1;
  }

H
Hongze Cheng 已提交
104
  *ppBt = pBt;
H
Hongze Cheng 已提交
105 106 107 108 109 110 111 112
  return 0;
}

int tdbBtreeClose(SBTree *pBt) {
  // TODO
  return 0;
}

H
more  
Hongze Cheng 已提交
113
int tdbBtreeCursor(SBtCursor *pCur, SBTree *pBt) {
H
more  
Hongze Cheng 已提交
114 115
  pCur->pBt = pBt;
  pCur->iPage = -1;
H
more  
Hongze Cheng 已提交
116 117 118
  pCur->pPage = NULL;
  pCur->idx = 0;

H
more  
Hongze Cheng 已提交
119 120 121
  return 0;
}

H
Hongze Cheng 已提交
122
int tdbBtCursorInsert(SBtCursor *pCur, const void *pKey, int kLen, const void *pVal, int vLen) {
H
Hongze Cheng 已提交
123 124
  int     ret;
  SPager *pPager;
H
Hongze Cheng 已提交
125 126 127 128 129 130 131

  ret = tdbBtCursorMoveTo(pCur, pKey, kLen);
  if (ret < 0) {
    // TODO: handle error
    return -1;
  }

H
more  
Hongze Cheng 已提交
132 133 134
  return 0;
}

H
Hongze Cheng 已提交
135
static int tdbBtCursorMoveTo(SBtCursor *pCur, const void *pKey, int kLen) {
H
Hongze Cheng 已提交
136 137
  int   ret;
  void *pCell;
H
more  
Hongze Cheng 已提交
138

H
refact  
Hongze Cheng 已提交
139 140 141 142
  // ret = tdbBtCursorMoveToRoot(pCur);
  // if (ret < 0) {
  //   return -1;
  // }
H
more  
Hongze Cheng 已提交
143

H
Hongze Cheng 已提交
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
  // if (pCur->pPage->pHdr->nCells == 0) {
  //   // Tree is empty
  // } else {
  //   for (;;) {
  //     int lidx, ridx, midx, c;

  //     pBtPage = pCur->pPage;
  //     lidx = 0;
  //     ridx = pBtPage->pHdr->nCells - 1;
  //     while (lidx <= ridx) {
  //       midx = (lidx + ridx) >> 1;
  //       pCell = (void *)(pBtPage->aData + pBtPage->aCellIdx[midx]);

  //       c = tdbCompareKeyAndCell(pKey, kLen, pCell);
  //       if (c == 0) {
  //         break;
  //       } else if (c < 0) {
  //         lidx = lidx + 1;
  //       } else {
  //         ridx = ridx - 1;
  //       }
  //     }
  //   }

  //   /* code */
  // }
H
more  
Hongze Cheng 已提交
170

H
Hongze Cheng 已提交
171 172
  return 0;
}
H
more  
Hongze Cheng 已提交
173

H
Hongze Cheng 已提交
174 175 176
static int tdbEncodeKeyValue(const void *pKey, int kLen, int kLenG, const void *pVal, int vLen, int vLenG, void *pBuf,
                             int *bLen) {
  u8 *pPtr;
H
more  
Hongze Cheng 已提交
177

H
Hongze Cheng 已提交
178 179 180 181 182 183 184 185 186 187 188
  ASSERT(kLen > 0 && vLen > 0);
  ASSERT(kLenG == TDB_VARIANT_LEN || kLenG == kLen);
  ASSERT(vLenG == TDB_VARIANT_LEN || vLenG == vLen);

  pPtr = (u8 *)pBuf;
  if (kLenG == TDB_VARIANT_LEN) {
    pPtr += tdbEncodeLength(pPtr, kLen);
  }

  if (vLenG == TDB_VARIANT_LEN) {
    pPtr += tdbEncodeLength(pPtr, vLen);
H
more  
Hongze Cheng 已提交
189
  }
H
more  
Hongze Cheng 已提交
190

H
Hongze Cheng 已提交
191 192 193 194 195 196 197
  memcpy(pPtr, pKey, kLen);
  pPtr += kLen;

  memcpy(pPtr, pVal, vLen);
  pPtr += vLen;

  *bLen = pPtr - (u8 *)pBuf;
H
more  
Hongze Cheng 已提交
198
  return 0;
H
Hongze Cheng 已提交
199 200 201
}

static int tdbDecodeKeyValue(const void *pBuf, void *pKey, int *kLen, void *pVal, int *vLen) {
H
more  
Hongze Cheng 已提交
202 203 204 205 206 207 208 209 210 211
  if (*kLen == TDB_VARIANT_LEN) {
    // Decode the key length
  }

  if (*vLen == TDB_VARIANT_LEN) {
    // Decode the value length
  }

  // TODO: decode the key and value

H
Hongze Cheng 已提交
212 213 214
  return 0;
}

H
more  
Hongze Cheng 已提交
215
static int tdbEncodeLength(u8 *pBuf, uint32_t len) {
H
Hongze Cheng 已提交
216 217 218 219 220 221 222 223 224 225
  int iCount = 0;

  while (len > 127) {
    pBuf[iCount++] = (u8)((len & 0xff) | 128);
    len >>= 7;
  }

  pBuf[iCount++] = (u8)len;

  return iCount;
H
more  
Hongze Cheng 已提交
226 227 228
}

static int tdbBtCursorMoveToRoot(SBtCursor *pCur) {
H
refact  
Hongze Cheng 已提交
229 230 231 232
  SBTree *pBt;
  SPager *pPager;
  SPage * pPage;
  int     ret;
H
more  
Hongze Cheng 已提交
233 234

  pBt = pCur->pBt;
H
refact  
Hongze Cheng 已提交
235
  pPager = pBt->pPager;
H
more  
Hongze Cheng 已提交
236

H
Hongze Cheng 已提交
237 238 239 240
  // pPage = tdbPagerGet(pPager, pBt->root, true);
  // if (pPage == NULL) {
  //   // TODO: handle error
  // }
H
more  
Hongze Cheng 已提交
241

H
Hongze Cheng 已提交
242 243 244 245 246
  // ret = tdbInitBtPage(pPage, &pBtPage);
  // if (ret < 0) {
  //   // TODO
  //   return 0;
  // }
H
more  
Hongze Cheng 已提交
247

H
Hongze Cheng 已提交
248 249
  // pCur->pPage = pBtPage;
  // pCur->iPage = 0;
H
more  
Hongze Cheng 已提交
250 251 252 253

  return 0;
}

H
more  
Hongze Cheng 已提交
254 255
static int tdbCompareKeyAndCell(const void *pKey, int kLen, const void *pCell) {
  /* TODO */
H
more  
Hongze Cheng 已提交
256
  return 0;
H
Hongze Cheng 已提交
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
}

static int tdbDefaultKeyCmprFn(const void *pKey1, int keyLen1, const void *pKey2, int keyLen2) {
  int mlen;
  int cret;

  ASSERT(keyLen1 > 0 && keyLen2 > 0 && pKey1 != NULL && pKey2 != NULL);

  mlen = keyLen1 < keyLen2 ? keyLen1 : keyLen2;
  cret = memcmp(pKey1, pKey2, mlen);
  if (cret == 0) {
    if (keyLen1 < keyLen2) {
      cret = -1;
    } else if (keyLen1 > keyLen2) {
      cret = 1;
    } else {
      cret = 0;
    }
  }
  return cret;
H
Hongze Cheng 已提交
277 278 279 280 281 282 283 284 285 286
}

static int tdbBtreeOpenImpl(SBTree *pBt) {
  // Try to get the root page of the an existing btree

  SPgno  pgno;
  SPage *pPage;
  int    ret;

  {
H
Hongze Cheng 已提交
287
    // 1. TODO: Search the main DB to check if the DB exists
H
Hongze Cheng 已提交
288 289 290 291 292 293 294 295 296
    pgno = 0;
  }

  if (pgno != 0) {
    pBt->root = pgno;
    return 0;
  }

  // Try to create a new database
H
Hongze Cheng 已提交
297 298 299 300 301 302 303
  SBtreeZeroPageArg zArg = {.flags = TDB_BTREE_ROOT | TDB_BTREE_LEAF, .pBt = pBt};
  ret = tdbPagerNewPage(pBt->pPager, &pgno, &pPage, tdbBtreeZeroPage, &zArg);
  if (ret < 0) {
    return -1;
  }

  // TODO: Unref the page
H
Hongze Cheng 已提交
304

H
Hongze Cheng 已提交
305 306
  ASSERT(pgno != 0);
  pBt->root = pgno;
H
Hongze Cheng 已提交
307

H
Hongze Cheng 已提交
308 309 310 311
  return 0;
}

static int tdbBtreeZeroPage(SPage *pPage, void *arg) {
H
Hongze Cheng 已提交
312 313 314 315 316 317
  u16     flags;
  SBTree *pBt;

  flags = ((SBtreeZeroPageArg *)arg)->flags;
  pBt = ((SBtreeZeroPageArg *)arg)->pBt;

H
Hongze Cheng 已提交
318 319 320 321
  pPage->pPageHdr = (SPageHdr *)pPage->pData;
  pPage->aCellIdx = (u16 *)(&(pPage->pPageHdr[1]));

  // Init the page header
H
Hongze Cheng 已提交
322 323
  pPage->pPageHdr->flags = flags;
  pPage->pPageHdr->nCells = 0;
H
Hongze Cheng 已提交
324
  pPage->pPageHdr->cellCont = pBt->pageSize;
H
Hongze Cheng 已提交
325 326
  pPage->pPageHdr->freeCell = 0;
  pPage->pPageHdr->nFree = 0;
H
Hongze Cheng 已提交
327

H
Hongze Cheng 已提交
328 329 330 331 332 333 334 335 336 337 338 339 340
  TDB_BTREE_ASSERT_FLAG(flags);

  if (TDB_BTREE_PAGE_IS_LEAF(pPage->pPageHdr->flags)) {
    pPage->kLen = pBt->keyLen;
    pPage->vLen = pBt->valLen;
    pPage->maxLocal = pBt->maxLeaf;
    pPage->minLocal = pBt->minLeaf;
  } else {
    pPage->kLen = pBt->keyLen;
    pPage->vLen = sizeof(SPgno);
    pPage->maxLocal = pBt->maxLocal;
    pPage->minLocal = pBt->minLocal;
  }
H
Hongze Cheng 已提交
341 342 343 344 345

  return 0;
}

static int tdbBtreeInitPage(SPage *pPage, void *arg) {
H
Hongze Cheng 已提交
346 347 348 349
  SBTree *pBt;

  pBt = (SBTree *)arg;

H
Hongze Cheng 已提交
350 351 352
  pPage->pPageHdr = (SPageHdr *)pPage->pData;
  pPage->aCellIdx = (u16 *)(&(pPage->pPageHdr[1]));

H
Hongze Cheng 已提交
353 354
  TDB_BTREE_ASSERT_FLAG(pPage->pPageHdr->flags);

H
Hongze Cheng 已提交
355
  // Init other fields
H
Hongze Cheng 已提交
356 357 358 359 360 361 362 363 364 365
  if (TDB_BTREE_PAGE_IS_LEAF(pPage->pPageHdr->flags)) {
    pPage->kLen = pBt->keyLen;
    pPage->vLen = pBt->valLen;
    pPage->maxLocal = pBt->maxLeaf;
    pPage->minLocal = pBt->minLeaf;
  } else {
    pPage->kLen = pBt->keyLen;
    pPage->vLen = sizeof(SPgno);
    pPage->maxLocal = pBt->maxLocal;
    pPage->minLocal = pBt->minLocal;
H
Hongze Cheng 已提交
366 367
  }

H
Hongze Cheng 已提交
368
  return 0;
H
more  
Hongze Cheng 已提交
369
}