tdbPage.h 8.7 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
  u8                *pData;
H
Hongze Cheng 已提交
50
  int                pageSize;
H
Hongze Cheng 已提交
51
  u8                 szOffset;
H
Hongze Cheng 已提交
52
  u8                 szPageHdr;
H
Hongze Cheng 已提交
53
  u8                 szFreeCell;
H
Hongze Cheng 已提交
54
  pthread_spinlock_t lock;
H
refact  
Hongze Cheng 已提交
55
  // Fields below used by pager and am
H
Hongze Cheng 已提交
56
  u8       *pPageHdr;
H
Hongze Cheng 已提交
57
  u8       *pAmHdr;
H
Hongze Cheng 已提交
58
  u8       *pCellIdx;
H
Hongze Cheng 已提交
59 60
  u8       *pFreeStart;
  u8       *pFreeEnd;
H
Hongze Cheng 已提交
61
  SPageFtr *pPageFtr;
H
Hongze Cheng 已提交
62 63
  int       kLen;
  int       vLen;
H
Hongze Cheng 已提交
64
  int       nFree;
H
Hongze Cheng 已提交
65 66 67
  int       maxLocal;
  int       minLocal;
  int       nOverflow;
H
Hongze Cheng 已提交
68
  SCell    *apOvfl[4];
H
Hongze Cheng 已提交
69
  int       aiOvfl[4];
H
Hongze Cheng 已提交
70 71
  // Fields used by SPCache
  TDB_PCACHE_PAGE
H
refact  
Hongze Cheng 已提交
72
};
H
Hongze Cheng 已提交
73

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

H
Hongze Cheng 已提交
77
/* For small page */
H
Hongze Cheng 已提交
78 79 80 81 82
#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 已提交
83
#define TDB_SPAGE_CELL_OFFSET_AT(pPage, idx) ((u16 *)((pPage)->pCellIdx))[idx]
H
Hongze Cheng 已提交
84

H
Hongze Cheng 已提交
85 86 87 88 89 90 91
#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 已提交
92
/* For large page */
H
Hongze Cheng 已提交
93 94 95 96 97
#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 已提交
98
#define TDB_LPAGE_CELL_OFFSET_AT(pPage, idx) TDB_GET_U24((pPage)->pCellIdx + idx * 3)
H
Hongze Cheng 已提交
99 100

#define TDB_LPAGE_FLAGS_SET(pPage, FLAGS)                TDB_LPAGE_FLAGS(pPage) = (flags)
H
Hongze Cheng 已提交
101 102 103 104
#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 已提交
105
#define TDB_LPAGE_CELL_OFFSET_AT_SET(pPage, idx, OFFSET) TDB_PUT_U24((pPage)->pCellIdx + idx * 3, OFFSET)
H
Hongze Cheng 已提交
106 107

/* For page */
H
Hongze Cheng 已提交
108 109 110 111 112
#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 已提交
113 114
#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 已提交
115 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

#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 已提交
170
#define TDB_PAGE_CELL_AT(pPage, idx) ((pPage)->pData + TDB_PAGE_CELL_OFFSET_AT(pPage, idx))
H
Hongze Cheng 已提交
171

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

H
Hongze Cheng 已提交
177
#define TDB_INIT_PAGE_LOCK(pPage)    pthread_spin_init(&((pPage)->lock), 0)
H
Hongze Cheng 已提交
178 179 180
#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 已提交
181 182 183 184 185 186 187 188 189 190 191 192
#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 已提交
193

H
Hongze Cheng 已提交
194
// For page ref
H
Hongze Cheng 已提交
195
#define TDB_INIT_PAGE_REF(pPage) ((pPage)->nRef = 0)
H
Hongze Cheng 已提交
196
#if 0
H
Hongze Cheng 已提交
197 198 199
#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 已提交
200
#else
H
Hongze Cheng 已提交
201 202 203
#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 已提交
204
#endif
H
Hongze Cheng 已提交
205

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

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

#endif /*_TDB_PAGE_H_*/