tdbBtree.c 5.6 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
struct SBTree {
H
more  
Hongze Cheng 已提交
19 20 21
  SPgno          root;
  int            keyLen;
  int            valLen;
H
refact  
Hongze Cheng 已提交
22
  SPager *       pPager;
H
more  
Hongze Cheng 已提交
23
  FKeyComparator kcmpr;
H
Hongze Cheng 已提交
24 25
};

H
Hongze Cheng 已提交
26
typedef struct SPgHdr {
H
more  
Hongze Cheng 已提交
27
  u8    flags;
H
more  
Hongze Cheng 已提交
28 29
  u8    fragmentTotalSize;
  u16   firstFreeCellOffset;
H
more  
Hongze Cheng 已提交
30 31 32 33 34
  u16   nCells;
  u16   pCell;
  i32   kLen;
  i32   vLen;
  SPgno rightChild;
H
Hongze Cheng 已提交
35 36
} SPgHdr;

H
Hongze Cheng 已提交
37
struct SBtPage {
H
Hongze Cheng 已提交
38 39
  SPgHdr *pHdr;
  u16 *   aCellIdx;
H
more  
Hongze Cheng 已提交
40
  u8 *    aData;
H
Hongze Cheng 已提交
41 42
};

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

H
Hongze Cheng 已提交
48 49
static int tdbBtCursorMoveTo(SBtCursor *pCur, const void *pKey, int kLen);
static int tdbEncodeLength(u8 *pBuf, uint len);
H
more  
Hongze Cheng 已提交
50 51
static int tdbBtCursorMoveToRoot(SBtCursor *pCur);
static int tdbInitBtPage(SPage *pPage, SBtPage **ppBtPage);
H
more  
Hongze Cheng 已提交
52
static int tdbCompareKeyAndCell(const void *pKey, int kLen, const void *pCell);
H
Hongze Cheng 已提交
53 54
static int tdbDefaultKeyCmprFn(const void *pKey1, int keyLen1, const void *pKey2, int keyLen2);

H
refact  
Hongze Cheng 已提交
55
int tdbBtreeOpen(SPgno rtPgno, int keyLen, int valLen, SPager *pPager, FKeyComparator kcmpr, SBTree **ppBt) {
H
Hongze Cheng 已提交
56
  SBTree *pBt;
H
more  
Hongze Cheng 已提交
57

H
Hongze Cheng 已提交
58
  *ppBt = NULL;
H
Hongze Cheng 已提交
59 60 61 62 63 64 65 66 67 68 69 70

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

  // pBt->root
  pBt->root = rtPgno;
  // pBt->keyLen
  pBt->keyLen = keyLen;
  // pBt->valLen
  pBt->valLen = valLen;
H
refact  
Hongze Cheng 已提交
71 72
  // pBt->pPager
  pBt->pPager = pPager;
H
Hongze Cheng 已提交
73 74 75 76
  // pBt->kcmpr
  pBt->kcmpr = kcmpr ? kcmpr : tdbDefaultKeyCmprFn;

  *ppBt = pBt;
H
Hongze Cheng 已提交
77 78 79 80 81 82 83 84
  return 0;
}

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

H
more  
Hongze Cheng 已提交
85
int tdbBtreeCursor(SBtCursor *pCur, SBTree *pBt) {
H
more  
Hongze Cheng 已提交
86 87
  pCur->pBt = pBt;
  pCur->iPage = -1;
H
more  
Hongze Cheng 已提交
88 89 90
  pCur->pPage = NULL;
  pCur->idx = 0;

H
more  
Hongze Cheng 已提交
91 92 93
  return 0;
}

H
Hongze Cheng 已提交
94
int tdbBtCursorInsert(SBtCursor *pCur, const void *pKey, int kLen, const void *pVal, int vLen) {
H
more  
Hongze Cheng 已提交
95
  int      ret;
H
refact  
Hongze Cheng 已提交
96
  SPager * pPager;
H
more  
Hongze Cheng 已提交
97
  SBtPage *pPage;
H
Hongze Cheng 已提交
98 99 100 101 102 103 104

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

H
more  
Hongze Cheng 已提交
105
  pPage = pCur->pPage;
H
Hongze Cheng 已提交
106

H
more  
Hongze Cheng 已提交
107 108 109
  return 0;
}

H
Hongze Cheng 已提交
110
static int tdbBtCursorMoveTo(SBtCursor *pCur, const void *pKey, int kLen) {
H
more  
Hongze Cheng 已提交
111 112 113
  int      ret;
  SBtPage *pBtPage;
  void *   pCell;
H
more  
Hongze Cheng 已提交
114 115

  ret = tdbBtCursorMoveToRoot(pCur);
H
more  
Hongze Cheng 已提交
116 117 118 119
  if (ret < 0) {
    return -1;
  }

H
refact  
Hongze Cheng 已提交
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
  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;
        }
H
more  
Hongze Cheng 已提交
141 142 143 144 145 146
      }
    }

    /* code */
  }

H
Hongze Cheng 已提交
147 148
  return 0;
}
H
more  
Hongze Cheng 已提交
149

H
Hongze Cheng 已提交
150 151 152
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 已提交
153

H
Hongze Cheng 已提交
154 155 156 157 158 159 160 161 162 163 164
  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 已提交
165
  }
H
more  
Hongze Cheng 已提交
166

H
Hongze Cheng 已提交
167 168 169 170 171 172 173
  memcpy(pPtr, pKey, kLen);
  pPtr += kLen;

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

  *bLen = pPtr - (u8 *)pBuf;
H
more  
Hongze Cheng 已提交
174
  return 0;
H
Hongze Cheng 已提交
175 176 177
}

static int tdbDecodeKeyValue(const void *pBuf, void *pKey, int *kLen, void *pVal, int *vLen) {
H
more  
Hongze Cheng 已提交
178 179 180 181 182 183 184 185 186 187
  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 已提交
188 189 190 191 192 193 194 195 196 197 198 199 200 201
  return 0;
}

static int tdbEncodeLength(u8 *pBuf, uint len) {
  int iCount = 0;

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

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

  return iCount;
H
more  
Hongze Cheng 已提交
202 203 204 205
}

static int tdbBtCursorMoveToRoot(SBtCursor *pCur) {
  SBTree * pBt;
H
refact  
Hongze Cheng 已提交
206
  SPager * pPager;
H
more  
Hongze Cheng 已提交
207 208 209 210 211
  SPage *  pPage;
  SBtPage *pBtPage;
  int      ret;

  pBt = pCur->pBt;
H
refact  
Hongze Cheng 已提交
212
  pPager = pBt->pPager;
H
more  
Hongze Cheng 已提交
213

H
refact  
Hongze Cheng 已提交
214
  pPage = tdbPagerGet(pPager, pBt->root);
H
more  
Hongze Cheng 已提交
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
  if (pPage == NULL) {
    // TODO: handle error
  }

  ret = tdbInitBtPage(pPage, &pBtPage);
  if (ret < 0) {
    // TODO
    return 0;
  }

  pCur->pPage = pBtPage;
  pCur->iPage = 0;

  return 0;
}

static int tdbInitBtPage(SPage *pPage, SBtPage **ppBtPage) {
H
more  
Hongze Cheng 已提交
232 233 234 235 236 237 238 239 240 241 242 243
  SBtPage *pBtPage;

  pBtPage = (SBtPage *)pPage->pExtra;
  pBtPage->pHdr = (SPgHdr *)pPage->pData;
  pBtPage->aCellIdx = (u16 *)(&((pBtPage->pHdr)[1]));
  pBtPage->aData = (u8 *)pPage->pData;

  *ppBtPage = pBtPage;
  return 0;
}
static int tdbCompareKeyAndCell(const void *pKey, int kLen, const void *pCell) {
  /* TODO */
H
more  
Hongze Cheng 已提交
244
  return 0;
H
Hongze Cheng 已提交
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
}

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
more  
Hongze Cheng 已提交
265
}