tskiplist.h 6.4 KB
Newer Older
H
hzcheng 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*
 * 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 TBASE_TSKIPLIST_H
#define TBASE_TSKIPLIST_H

#ifdef __cplusplus
extern "C" {
#endif

#define MAX_SKIP_LIST_LEVEL 20

#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>

S
slguan 已提交
29
#include "os.h"
H
hzcheng 已提交
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
#include "ttypes.h"

/*
 * key of each node
 * todo move to as the global structure in all search codes...
 */

const static size_t SKIP_LIST_STR_KEY_LENGTH_THRESHOLD = 15;
typedef tVariant    tSkipListKey;

typedef enum tSkipListPointQueryType {
  INCLUDE_POINT_QUERY,
  EXCLUDE_POINT_QUERY,
} tSkipListPointQueryType;

typedef struct tSkipListNode {
S
slguan 已提交
46 47
  uint16_t nLevel;
  char *   pData;
H
hzcheng 已提交
48 49 50

  struct tSkipListNode **pForward;
  struct tSkipListNode **pBackward;
51 52

  tSkipListKey key;
H
hzcheng 已提交
53 54 55 56 57 58
} tSkipListNode;

/*
 * @version 0.2
 * @date   2017/11/12
 * the simple version of SkipList.
S
slguan 已提交
59
 * for multi-thread safe purpose, we employ pthread_rwlock_t to guarantee to generate
H
hzcheng 已提交
60
 * deterministic result. Later, we will remove the lock in SkipList to further
S
slguan 已提交
61 62
 * enhance the performance. In this case, one should use the concurrent skip list (by
 * using michael-scott algorithm) instead of this simple version in a multi-thread
H
hzcheng 已提交
63 64 65
 * environment, to achieve higher performance of read/write operations.
 *
 * Note: Duplicated primary key situation.
S
slguan 已提交
66
 * In case of duplicated primary key, two ways can be employed to handle this situation:
H
hzcheng 已提交
67
 * 1. add as normal insertion with out special process.
S
slguan 已提交
68 69 70 71 72 73
 * 2. add an overflow pointer at each list node, all nodes with the same key will be added
 *    in the overflow pointer. In this case, the total steps of each search will be reduced significantly.
 *    Currently, we implement the skip list in a line with the first means, maybe refactor it soon.
 *
 *    Memory consumption: the memory alignment causes many memory wasted. So, employ a memory
 *    pool will significantly reduce the total memory consumption, as well as the calloc/malloc operation costs.
H
hzcheng 已提交
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
 *
 * 3. use the iterator pattern to refactor all routines to make it more clean
 */

// state struct, record following information:
// number of links in each level.
// avg search steps, for latest 1000 queries
// avg search rsp time, for latest 1000 queries
// total memory size
typedef struct tSkipListState {
  // in bytes, sizeof(tSkipList)+sizeof(tSkipListNode)*tSkipList->nSize
  uint64_t nTotalMemSize;
  uint64_t nLevelNodeCnt[MAX_SKIP_LIST_LEVEL];
  uint64_t queryCount;  // total query count

  /*
   * only record latest 1000 queries
   * when the value==1000, = 0,
   * nTotalStepsForQueries = 0,
   * nTotalElapsedTimeForQueries = 0
   */
  uint64_t nRecQueries;
  uint16_t nTotalStepsForQueries;
  uint64_t nTotalElapsedTimeForQueries;

  uint16_t nInsertObjs;
  uint16_t nTotalStepsForInsert;
  uint64_t nTotalElapsedTimeForInsert;
} tSkipListState;

typedef struct tSkipList {
  tSkipListNode pHead;
  uint64_t      nSize;
S
slguan 已提交
107 108 109 110
  uint16_t      nMaxLevel;
  uint16_t      nLevel;
  uint16_t      keyType;
  uint16_t      nMaxKeyLen;
H
hzcheng 已提交
111 112

  __compar_fn_t    comparator;
S
slguan 已提交
113 114
  pthread_rwlock_t lock;   // will be removed soon
  tSkipListState   state;  // skiplist state
H
hzcheng 已提交
115 116
} tSkipList;

S
slguan 已提交
117 118 119 120 121 122 123 124 125 126 127 128
/*
 * iterate the skiplist
 * this will cause the multi-thread problem, when the skiplist is destroyed, the iterate may
 * continue iterating the skiplist, so add the reference count for skiplist
 * TODO add the ref for skiplist when one iterator is created
 */
typedef struct SSkipListIterator {
  tSkipList *    pSkipList;
  tSkipListNode *cur;
  int64_t        num;
} SSkipListIterator;

H
hzcheng 已提交
129 130
/*
 * query condition structure to denote the range query
S
slguan 已提交
131
 * todo merge the point query cond with range query condition
H
hzcheng 已提交
132 133 134 135 136
 */
typedef struct tSKipListQueryCond {
  // when the upper bounding == lower bounding, it is a point query
  tSkipListKey lowerBnd;
  tSkipListKey upperBnd;
S
slguan 已提交
137 138
  int32_t      lowerBndRelOptr;  // relation operator to denote if lower bound is
  int32_t      upperBndRelOptr;  // included or not
H
hzcheng 已提交
139 140
} tSKipListQueryCond;

S
slguan 已提交
141
tSkipList *tSkipListCreate(int16_t nMaxLevel, int16_t keyType, int16_t nMaxKeyLen);
H
hzcheng 已提交
142

S
slguan 已提交
143
void *tSkipListDestroy(tSkipList *pSkipList);
H
hzcheng 已提交
144 145 146 147 148 149 150 151 152 153 154 155

// create skip list key
tSkipListKey tSkipListCreateKey(int32_t type, char *val, size_t keyLength);

// destroy skip list key
void tSkipListDestroyKey(tSkipListKey *pKey);

// put data into skiplist
tSkipListNode *tSkipListPut(tSkipList *pSkipList, void *pData, tSkipListKey *pKey, int32_t insertIdenticalKey);

/*
 * get only *one* node of which key is equalled to pKey, even there are more
156
 * than one nodes are of the same key
H
hzcheng 已提交
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
 */
tSkipListNode *tSkipListGetOne(tSkipList *pSkipList, tSkipListKey *pKey);

/*
 * get all data with the same keys
 */
int32_t tSkipListGets(tSkipList *pSkipList, tSkipListKey *pKey, tSkipListNode ***pRes);

int32_t tSkipListIterateList(tSkipList *pSkipList, tSkipListNode ***pRes, bool (*fp)(tSkipListNode *, void *),
                             void *param);

/*
 * remove only one node of the pKey value.
 * If more than one node has the same value, any one will be removed
 *
 * @Return
 * true: one node has been removed
 * false: no node has been removed
 */
bool tSkipListRemove(tSkipList *pSkipList, tSkipListKey *pKey);

/*
 * remove the specified node in parameters
 */
void tSkipListRemoveNode(tSkipList *pSkipList, tSkipListNode *pNode);

// for debug purpose only
void tSkipListPrint(tSkipList *pSkipList, int16_t nlevel);

/*
 * range query & single point query function
 */
int32_t tSkipListQuery(tSkipList *pSkipList, tSKipListQueryCond *pQueryCond, tSkipListNode ***pResult);

/*
 * include/exclude point query
 */
int32_t tSkipListPointQuery(tSkipList *pSkipList, tSkipListKey *pKey, int32_t numOfKey, tSkipListPointQueryType type,
                            tSkipListNode ***pResult);

S
slguan 已提交
197 198 199 200
int32_t tSkipListIteratorReset(tSkipList *pSkipList, SSkipListIterator *iter);
bool tSkipListIteratorNext(SSkipListIterator *iter);
tSkipListNode *tSkipListIteratorGet(SSkipListIterator *iter);

H
hzcheng 已提交
201 202 203 204 205
#ifdef __cplusplus
}
#endif

#endif  // TBASE_TSKIPLIST_H