tdbPage.h 8.8 KB
Newer Older
H
Hongze Cheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * 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/>.
 */

#ifndef _TDB_PAGE_H_
#define _TDB_PAGE_H_

#ifdef __cplusplus
extern "C" {
#endif

H
Hongze Cheng 已提交
23 24
typedef u8 SCell;

H
Hongze Cheng 已提交
25
// Page header (pageSize < 65536 (64K))
H
Hongze Cheng 已提交
26
typedef struct __attribute__((__packed__)) {
H
Hongze Cheng 已提交
27
  u16 flags;
H
Hongze Cheng 已提交
28 29 30 31
  u16 nCells;  // number of cells
  u16 cCells;  // cell content offset
  u16 fCell;   // first free cell offset
  u16 nFree;   // total fragment bytes in this page
H
Hongze Cheng 已提交
32 33
} SPageHdr;

H
Hongze Cheng 已提交
34
// Large page header (pageSize >= 65536 (64K))
H
Hongze Cheng 已提交
35 36 37
typedef struct __attribute__((__packed__)) {
  u16 flags;
  u8  nCells[3];
H
refact  
Hongze Cheng 已提交
38 39
  u8  cCells[3];
  u8  fCell[3];
H
Hongze Cheng 已提交
40
  u8  nFree[3];
H
Hongze Cheng 已提交
41
} SPageHdrL;
H
Hongze Cheng 已提交
42

H
Hongze Cheng 已提交
43
// Page footer
H
Hongze Cheng 已提交
44 45 46 47
typedef struct __attribute__((__packed__)) {
  u8 cksm[4];
} SPageFtr;

H
refact  
Hongze Cheng 已提交
48
struct SPage {
H
Hongze Cheng 已提交
49
  pthread_spinlock_t lock;
H
Hongze Cheng 已提交
50
  u8                *pData;
H
Hongze Cheng 已提交
51
  int                pageSize;
H
Hongze Cheng 已提交
52
  u8                 szOffset;
H
Hongze Cheng 已提交
53
  u8                 szPageHdr;
H
Hongze Cheng 已提交
54
  u8                 szFreeCell;
H
refact  
Hongze Cheng 已提交
55
  // Fields below used by pager and am
H
Hongze Cheng 已提交
56
  u8        szAmHdr;
H
Hongze Cheng 已提交
57
  u8       *pPageHdr;
H
Hongze Cheng 已提交
58
  u8       *pAmHdr;
H
Hongze Cheng 已提交
59
  u8       *pCellIdx;
H
Hongze Cheng 已提交
60 61
  u8       *pFreeStart;
  u8       *pFreeEnd;
H
Hongze Cheng 已提交
62
  SPageFtr *pPageFtr;
H
Hongze Cheng 已提交
63 64
  int       kLen;  // key length of the page, -1 for unknown
  int       vLen;  // value length of the page, -1 for unknown
H
Hongze Cheng 已提交
65
  int       nFree;
H
Hongze Cheng 已提交
66 67 68
  int       maxLocal;
  int       minLocal;
  int       nOverflow;
H
Hongze Cheng 已提交
69
  SCell    *apOvfl[4];
H
Hongze Cheng 已提交
70
  int       aiOvfl[4];
H
Hongze Cheng 已提交
71 72
  // Fields used by SPCache
  TDB_PCACHE_PAGE
H
refact  
Hongze Cheng 已提交
73
};
H
Hongze Cheng 已提交
74

H
Hongze Cheng 已提交
75
// Macros
H
Hongze Cheng 已提交
76 77
#define TDB_IS_LARGE_PAGE(pPage) ((pPage)->szOffset == 3)

H
Hongze Cheng 已提交
78
/* For small page */
H
Hongze Cheng 已提交
79 80 81 82 83
#define TDB_SPAGE_FLAGS(pPage)               (((SPageHdr *)(pPage)->pPageHdr)->flags)
#define TDB_SPAGE_NCELLS(pPage)              (((SPageHdr *)(pPage)->pPageHdr)->nCells)
#define TDB_SPAGE_CCELLS(pPage)              (((SPageHdr *)(pPage)->pPageHdr)->cCells)
#define TDB_SPAGE_FCELL(pPage)               (((SPageHdr *)(pPage)->pPageHdr)->fCell)
#define TDB_SPAGE_NFREE(pPage)               (((SPageHdr *)(pPage)->pPageHdr)->nFree)
H
Hongze Cheng 已提交
84
#define TDB_SPAGE_CELL_OFFSET_AT(pPage, idx) ((u16 *)((pPage)->pCellIdx))[idx]
H
Hongze Cheng 已提交
85

H
Hongze Cheng 已提交
86 87 88 89 90 91 92
#define TDB_SPAGE_FLAGS_SET(pPage, FLAGS)                TDB_SPAGE_FLAGS(pPage) = (FLAGS)
#define TDB_SPAGE_NCELLS_SET(pPage, NCELLS)              TDB_SPAGE_NCELLS(pPage) = (NCELLS)
#define TDB_SPAGE_CCELLS_SET(pPage, CCELLS)              TDB_SPAGE_CCELLS(pPage) = (CCELLS)
#define TDB_SPAGE_FCELL_SET(pPage, FCELL)                TDB_SPAGE_FCELL(pPage) = (FCELL)
#define TDB_SPAGE_NFREE_SET(pPage, NFREE)                TDB_SPAGE_NFREE(pPage) = (NFREE)
#define TDB_SPAGE_CELL_OFFSET_AT_SET(pPage, idx, OFFSET) TDB_SPAGE_CELL_OFFSET_AT(pPage, idx) = (OFFSET)

H
Hongze Cheng 已提交
93
/* For large page */
H
Hongze Cheng 已提交
94 95 96 97 98
#define TDB_LPAGE_FLAGS(pPage)               (((SPageHdrL *)(pPage)->pPageHdr)->flags)
#define TDB_LPAGE_NCELLS(pPage)              TDB_GET_U24(((SPageHdrL *)(pPage)->pPageHdr)->nCells)
#define TDB_LPAGE_CCELLS(pPage)              TDB_GET_U24(((SPageHdrL *)(pPage)->pPageHdr)->cCells)
#define TDB_LPAGE_FCELL(pPage)               TDB_GET_U24(((SPageHdrL *)(pPage)->pPageHdr)->fCell)
#define TDB_LPAGE_NFREE(pPage)               TDB_GET_U24(((SPageHdrL *)(pPage)->pPageHdr)->nFree)
H
Hongze Cheng 已提交
99
#define TDB_LPAGE_CELL_OFFSET_AT(pPage, idx) TDB_GET_U24((pPage)->pCellIdx + idx * 3)
H
Hongze Cheng 已提交
100 101

#define TDB_LPAGE_FLAGS_SET(pPage, FLAGS)                TDB_LPAGE_FLAGS(pPage) = (flags)
H
Hongze Cheng 已提交
102 103 104 105
#define TDB_LPAGE_NCELLS_SET(pPage, NCELLS)              TDB_PUT_U24(((SPageHdrL *)(pPage)->pPageHdr)->nCells, NCELLS)
#define TDB_LPAGE_CCELLS_SET(pPage, CCELLS)              TDB_PUT_U24(((SPageHdrL *)(pPage)->pPageHdr)->cCells, CCELLS)
#define TDB_LPAGE_FCELL_SET(pPage, FCELL)                TDB_PUT_U24(((SPageHdrL *)(pPage)->pPageHdr)->fCell, FCELL)
#define TDB_LPAGE_NFREE_SET(pPage, NFREE)                TDB_PUT_U24(((SPageHdrL *)(pPage)->pPageHdr)->nFree, NFREE)
H
Hongze Cheng 已提交
106
#define TDB_LPAGE_CELL_OFFSET_AT_SET(pPage, idx, OFFSET) TDB_PUT_U24((pPage)->pCellIdx + idx * 3, OFFSET)
H
Hongze Cheng 已提交
107 108

/* For page */
H
Hongze Cheng 已提交
109 110 111 112 113
#define TDB_PAGE_FLAGS(pPage)  (TDB_IS_LARGE_PAGE(pPage) ? TDB_LPAGE_FLAGS(pPage) : TDB_SPAGE_FLAGS(pPage))
#define TDB_PAGE_NCELLS(pPage) (TDB_IS_LARGE_PAGE(pPage) ? TDB_LPAGE_NCELLS(pPage) : TDB_SPAGE_NCELLS(pPage))
#define TDB_PAGE_CCELLS(pPage) (TDB_IS_LARGE_PAGE(pPage) ? TDB_LPAGE_CCELLS(pPage) : TDB_SPAGE_CCELLS(pPage))
#define TDB_PAGE_FCELL(pPage)  (TDB_IS_LARGE_PAGE(pPage) ? TDB_LPAGE_FCELL(pPage) : TDB_SPAGE_FCELL(pPage))
#define TDB_PAGE_NFREE(pPage)  (TDB_IS_LARGE_PAGE(pPage) ? TDB_LPAGE_NFREE(pPage) : TDB_SPAGE_NFREE(pPage))
H
Hongze Cheng 已提交
114 115
#define TDB_PAGE_CELL_OFFSET_AT(pPage, idx) \
  (TDB_IS_LARGE_PAGE(pPage) ? TDB_LPAGE_CELL_OFFSET_AT(pPage, idx) : TDB_SPAGE_CELL_OFFSET_AT(pPage, idx))
H
Hongze Cheng 已提交
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 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 164 165 166 167 168 169 170

#define TDB_PAGE_FLAGS_SET(pPage, FLAGS) \
  do {                                   \
    if (TDB_IS_LARGE_PAGE(pPage)) {      \
      TDB_LPAGE_FLAGS_SET(pPage, FLAGS); \
    } else {                             \
      TDB_SPAGE_FLAGS_SET(pPage, FLAGS); \
    }                                    \
  } while (0)

#define TDB_PAGE_NCELLS_SET(pPage, NCELLS) \
  do {                                     \
    if (TDB_IS_LARGE_PAGE(pPage)) {        \
      TDB_LPAGE_NCELLS_SET(pPage, NCELLS); \
    } else {                               \
      TDB_SPAGE_NCELLS_SET(pPage, NCELLS); \
    }                                      \
  } while (0)

#define TDB_PAGE_CCELLS_SET(pPage, CCELLS) \
  do {                                     \
    if (TDB_IS_LARGE_PAGE(pPage)) {        \
      TDB_LPAGE_CCELLS_SET(pPage, CCELLS); \
    } else {                               \
      TDB_SPAGE_CCELLS_SET(pPage, CCELLS); \
    }                                      \
  } while (0)

#define TDB_PAGE_FCELL_SET(pPage, FCELL) \
  do {                                   \
    if (TDB_IS_LARGE_PAGE(pPage)) {      \
      TDB_LPAGE_FCELL_SET(pPage, FCELL); \
    } else {                             \
      TDB_SPAGE_FCELL_SET(pPage, FCELL); \
    }                                    \
  } while (0)

#define TDB_PAGE_NFREE_SET(pPage, NFREE) \
  do {                                   \
    if (TDB_IS_LARGE_PAGE(pPage)) {      \
      TDB_LPAGE_NFREE_SET(pPage, NFREE); \
    } else {                             \
      TDB_SPAGE_NFREE_SET(pPage, NFREE); \
    }                                    \
  } while (0)

#define TDB_PAGE_CELL_OFFSET_AT_SET(pPage, idx, OFFSET) \
  do {                                                  \
    if (TDB_IS_LARGE_PAGE(pPage)) {                     \
      TDB_LPAGE_CELL_OFFSET_AT_SET(pPage, idx, OFFSET); \
    } else {                                            \
      TDB_SPAGE_CELL_OFFSET_AT_SET(pPage, idx, OFFSET); \
    }                                                   \
  } while (0)

H
Hongze Cheng 已提交
171
#define TDB_PAGE_CELL_AT(pPage, idx) ((pPage)->pData + TDB_PAGE_CELL_OFFSET_AT(pPage, idx))
H
Hongze Cheng 已提交
172

H
Hongze Cheng 已提交
173
// For page lock
H
Hongze Cheng 已提交
174 175 176 177
#define P_LOCK_SUCC 0
#define P_LOCK_BUSY 1
#define P_LOCK_FAIL -1

H
Hongze Cheng 已提交
178
#define TDB_INIT_PAGE_LOCK(pPage)    pthread_spin_init(&((pPage)->lock), 0)
H
Hongze Cheng 已提交
179 180 181
#define TDB_DESTROY_PAGE_LOCK(pPage) pthread_spin_destroy(&((pPage)->lock))
#define TDB_LOCK_PAGE(pPage)         pthread_spin_lock(&((pPage)->lock))
#define TDB_UNLOCK_PAGE(pPage)       pthread_spin_unlock(&((pPage)->lock))
H
Hongze Cheng 已提交
182 183 184 185 186 187 188 189 190 191 192 193
#define TDB_TRY_LOCK_PAGE(pPage)                       \
  ({                                                   \
    int ret;                                           \
    if (pthread_spin_trylock(&((pPage)->lock)) == 0) { \
      ret = P_LOCK_SUCC;                               \
    } else if (errno == EBUSY) {                       \
      ret = P_LOCK_BUSY;                               \
    } else {                                           \
      ret = P_LOCK_FAIL;                               \
    }                                                  \
    ret;                                               \
  })
H
Hongze Cheng 已提交
194

H
Hongze Cheng 已提交
195
// For page ref
H
Hongze Cheng 已提交
196
#define TDB_INIT_PAGE_REF(pPage) ((pPage)->nRef = 0)
H
Hongze Cheng 已提交
197
#if 0
H
Hongze Cheng 已提交
198 199 200
#define TDB_REF_PAGE(pPage)     (++(pPage)->nRef)
#define TDB_UNREF_PAGE(pPage)   (--(pPage)->nRef)
#define TDB_GET_PAGE_REF(pPage) ((pPage)->nRef)
H
Hongze Cheng 已提交
201
#else
H
Hongze Cheng 已提交
202 203 204
#define TDB_REF_PAGE(pPage)     atomic_add_fetch_32(&((pPage)->nRef), 1)
#define TDB_UNREF_PAGE(pPage)   atomic_sub_fetch_32(&((pPage)->nRef), 1)
#define TDB_GET_PAGE_REF(pPage) atomic_load_32(&((pPage)->nRef))
H
Hongze Cheng 已提交
205
#endif
H
Hongze Cheng 已提交
206

H
Hongze Cheng 已提交
207
// APIs
H
Hongze Cheng 已提交
208
int tdbPageCreate(int pageSize, SPage **ppPage, void *(*xMalloc)(void *, size_t), void *arg);
H
Hongze Cheng 已提交
209
int tdbPageDestroy(SPage *pPage, void (*xFree)(void *arg, void *ptr), void *arg);
H
Hongze Cheng 已提交
210
int tdbPageInsertCell(SPage *pPage, int idx, SCell *pCell, int szCell);
H
Hongze Cheng 已提交
211 212
int tdbPageDropCell(SPage *pPage, int idx);

H
Hongze Cheng 已提交
213 214 215 216 217
#ifdef __cplusplus
}
#endif

#endif /*_TDB_PAGE_H_*/