├── Inside-The-C-Object-Model ├── object.c └── object.cpp ├── Introduction-to-Algorithms └── BTree.py ├── Large-Scale-Distributed-Storage-System ├── bitcask.py ├── bptree.py ├── lsm_tree.py ├── skiplist.py ├── skiplist │ ├── makefile │ ├── src │ │ ├── skiplist.cpp │ │ └── skiplist.h │ └── test │ │ └── skiplist_test.cpp └── skiplist0.2 │ ├── Readme.md │ ├── makefile │ ├── src │ ├── skiplist.cpp │ └── skiplist.h │ └── test │ └── skiplist_test.cpp └── README.md /Inside-The-C-Object-Model/object.c: -------------------------------------------------------------------------------- 1 | /************** 2 | *convert C++ Class to C 3 | *********************** 4 | class A 5 | { 6 | public: 7 | int max() 8 | { 9 | int m = (a > b ? a : b); 10 | return m; 11 | } 12 | static void bar() 13 | { 14 | printf("%d\n",c); 15 | } 16 | public: 17 | int a; 18 | int b; 19 | static int c; 20 | }; 21 | int A::c = 20; 22 | 23 | int main() 24 | { 25 | A a; 26 | a.a = 10; 27 | a.b = 20; 28 | printf("%d\n",a.max()); 29 | 30 | A::bar(); 31 | 32 | return 0; 33 | } 34 | ************/ 35 | #include 36 | 37 | /*class object*/ 38 | typedef struct A{ 39 | int a; 40 | int b; 41 | }A; 42 | // static member definition 43 | int A_c_static = 20; 44 | 45 | //convert nonstatic member function to nonmember function 46 | //add this pointer 47 | int A_max_vi(A * _this) 48 | { 49 | //change to reference path 50 | int m = (_this->a > _this->b ? _this->a : _this->b); 51 | return m; 52 | } 53 | //convert static member function to nonmember function 54 | void A_bar_vv() 55 | { 56 | //static member reference 57 | printf("%d\n",A_c_static); 58 | } 59 | 60 | int main() 61 | { 62 | A a; 63 | a.a = 10; 64 | a.b = 20; 65 | //change reference 66 | printf("%d\n",A_max_vi(&a)); 67 | 68 | A_bar_vv(); 69 | 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /Inside-The-C-Object-Model/object.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Inside The C++ Object Model 3 | */ 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | class A 9 | { 10 | public: 11 | int max() 12 | { 13 | int m = (a > b ? a : b); 14 | return m; 15 | } 16 | static void bar() 17 | { 18 | cout<=self.middle_size(): 158 | return 1 159 | return 0 160 | def can_borrow_right(self,node): 161 | pi = node.parent.childs.index(node) 162 | parent = node.parent 163 | if pi != len(parent.childs)-1: 164 | if len(parent.childs[pi+1].entitys) >=self.middle_size(): 165 | return 1 166 | return 0 167 | def borrow_left(self,node): 168 | pi = node.parent.childs.index(node) 169 | 170 | parent = node.parent 171 | if pi == len(parent.childs)-1: 172 | node.add_entity(parent.entitys[-1]) 173 | parent.del_entity(parent.entitys[-1]) 174 | else: 175 | node.add_entity(parent.entitys[pi]) 176 | parent.del_entity(parent.entitys[pi]) 177 | 178 | left = node.parent.childs[pi-1] 179 | parent.add_entity(left.entitys[-1]) 180 | left.del_entity(left.entitys[-1]) 181 | def borrow_right(self,node): 182 | pi = node.parent.childs.index(node) 183 | 184 | parent = node.parent 185 | 186 | node.add_entity(parent.entitys[pi]) 187 | parent.del_entity(parent.entitys[pi]) 188 | 189 | right = node.parent.childs[pi+1] 190 | parent.add_entity(right.entitys[0]) 191 | right.del_entity(right.entitys[0]) 192 | 193 | def combine(self,node): 194 | pi = node.parent.childs.index(node) 195 | parent = node.parent 196 | 197 | if pi == len(parent.childs)-1: 198 | node.add_entity(parent.entitys[-1]) 199 | parent.del_entity(parent.entitys[-1]) 200 | 201 | node.join_node(parent.childs[pi-1]) 202 | parent.del_child(parent.childs[pi-1]) 203 | else: 204 | node.add_entity(parent.entitys[pi]) 205 | parent.del_entity(parent.entitys[pi]) 206 | 207 | node.join_node(parent.childs[pi+1]) 208 | parent.del_child(parent.childs[pi+1]) 209 | 210 | def empty(self): 211 | return self.length==0 212 | def __find_node(self,key): 213 | '''通过key值查询一个数据在那个节点,找的并返回该节点''' 214 | 215 | if self.root: 216 | curr = self.root 217 | while curr.isleaf() != None: 218 | for i,entity in enumerate(curr.entitys): 219 | if entity.key > key: 220 | curr = curr.childs[i] 221 | break 222 | if entity.key == key: 223 | return curr 224 | else: 225 | pass 226 | else: 227 | curr = curr.childs[-1] 228 | if curr.search(key): 229 | return curr 230 | def __split(self,node): 231 | ''' 232 | 分裂一个节点,规则为: 233 | 1.中间节点前面的数据项移到父节点 234 | 2.新建一个右兄弟节点,将中间节点右边的数据移到新节点 235 | ''' 236 | middle = len(node.entitys)/2 237 | top = node.entitys[middle] 238 | 239 | right = Node() 240 | 241 | for entity in node.entitys[middle+1:]: 242 | right.add_entity(entity) 243 | for child in node.childs[middle+1:]: 244 | right.add_child(child) 245 | 246 | node.entitys = node.entitys[:middle] 247 | node.childs = node.childs[:middle+1] 248 | 249 | parent = node.parent 250 | 251 | if parent: 252 | parent.add_entity(top) 253 | parent.add_child(right) 254 | 255 | if len(parent.entitys) > self.size: 256 | self.__split(parent) 257 | else: 258 | self.root = Node() 259 | self.root.add_entity(top) 260 | self.root.add_child(node) 261 | self.root.add_child(right) 262 | def insert_test(t): 263 | 264 | t.insert(20,'200') 265 | t.insert(40,'400') 266 | t.insert(60,'600') 267 | t.insert(70,'700') 268 | t.insert(80,'800') 269 | t.insert(10,'100') 270 | t.insert(50,'500') 271 | t.insert(51,'510') 272 | t.insert(52,'520') 273 | t.insert(53,'530') 274 | t.insert(54,'540') 275 | t.insert(55,'550') 276 | t.insert(56,'560') 277 | t.insert(57,'570') 278 | t.insert(58,'580') 279 | t.insert(81,'810') 280 | t.insert(82,'820') 281 | t.insert(83,'830') 282 | def delete_test(t): 283 | t.delete(10) 284 | t.delete(52) 285 | t.delete(51) 286 | 287 | def print_entitys(t): 288 | for i in t.root.entitys: 289 | print i.key,i.value 290 | print '-----------' 291 | def print_nodes(t): 292 | for i in t.entitys: 293 | print i.key,i.value 294 | def print_level(node,f=1): 295 | for j,e in enumerate(node.entitys): 296 | print '-'*4*f,e.key,e.value 297 | for i in node.childs: 298 | print_level(i,f+1) 299 | print '-'*4*(f+1) 300 | if i.parent !=node: 301 | print "error parent" 302 | 303 | 304 | 305 | if __name__ == '__main__': 306 | t = BTree(4) 307 | insert_test(t) 308 | delete_test(t) 309 | print_level(t.root) 310 | 311 | -------------------------------------------------------------------------------- /Large-Scale-Distributed-Storage-System/bitcask.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os 4 | import shutil 5 | import cPickle as pickle 6 | from glob import glob 7 | from binascii import crc32 8 | from datetime import datetime 9 | 10 | 11 | class Bitcask(object): 12 | def __init__(self,THRESHOLD=10000,path="./"): 13 | self.TABLE = {} 14 | self.THRESHOLD = THRESHOLD 15 | self.path = path 16 | self.curr_active = max([int(f.replace('.sst', '').replace(self.path,'')) for f in glob(path+'*.sst')] or [1]) 17 | 18 | if os.path.exists(path) == False: 19 | shutil.mkdir(path) 20 | 21 | def get(self,key): 22 | '''根据Key获取对应的值''' 23 | record = self.__get_record(key) 24 | if record != None: 25 | return record[5] 26 | return None 27 | 28 | def put(self,key, value): 29 | '''将key,value写入数据文件''' 30 | key_size = len(key) 31 | 32 | value_size = 0 33 | if value is not None: 34 | value_size = len(value) 35 | 36 | ts = datetime.now() 37 | crc = crc32('{0}{1}{2}{3}{4}'.format( 38 | ts, key_size, value_size, key, value)) 39 | info = self.__io_write(crc, ts, key_size, value_size, key, value) 40 | self.TABLE[key] = info 41 | return True 42 | 43 | def delete(self,key): 44 | '''删除Key对应的记录''' 45 | return self.put(key,None) 46 | def update(self,key): 47 | '''更新Key对应的记录''' 48 | return self.put(key,value) 49 | 50 | def load_data(self,path=None): 51 | '''指定路径,加载该文件夹目录下所有数据文件''' 52 | if path is not None: 53 | self.path = path 54 | if os.path.exists(path) == False: 55 | shutil.mkdir(path) 56 | 57 | for filename in glob(self.path+"*.sst"): 58 | self.load_file(filename) 59 | 60 | def load_file(self,filename): 61 | '''加载文件名为filename的数据文件''' 62 | f = open(filename) 63 | data = f.read() 64 | list_items = data.split("t.") 65 | 66 | start = 0 67 | length = 0 68 | for item in list_items[:-1]: 69 | s= item+"t." 70 | record = pickle.loads(s) 71 | length = len(item)+2 72 | if self.TABLE.has_key(record[4]) is True: 73 | ts1 = record[1] 74 | ts2 = self.__get_record(record[4])[1] 75 | if ts1 > ts2: 76 | self.TABLE[record[4]]=(filename,start,length) 77 | else: 78 | self.TABLE[record[4]]=(filename,start,length) 79 | start += length 80 | f.close() 81 | 82 | def __get_record(self,key): 83 | '''根据key取出数据文件中对应的整条记录''' 84 | info = self.TABLE.get(key) 85 | print info,type(info) 86 | if not info: 87 | return None 88 | pickled_data = self.__io_read(*info) 89 | data = pickle.loads(pickled_data) 90 | # check tuple, crc, the same key? 91 | return data 92 | 93 | 94 | def __io_read(self,filename, start, length): 95 | '''读取未经反序列化的文件数据''' 96 | with open(filename, 'rb') as f: 97 | f.seek(start) 98 | return f.read(length) 99 | 100 | def __io_write(self,crc, ts, key_size, value_size, key, value): 101 | '''将记录序列化后写入文件''' 102 | active_filename = '%s%s.sst' %(self.path,self.curr_active) 103 | 104 | try: 105 | if os.path.getsize(active_filename) >= self.THRESHOLD: 106 | self.curr_active += 1 107 | active_filename = '%s%s.sst' % self.path,self.curr_active 108 | except: 109 | pass 110 | with open(active_filename, 'a') as f: 111 | data = pickle.dumps((crc, ts, key_size, value_size, key, value)) 112 | start = f.tell() 113 | length = len(data) 114 | f.write(data) 115 | return active_filename, start, length 116 | 117 | 118 | def list_keys(self): 119 | '''返回所有记录的Key列表''' 120 | return self.TABLE.keys() 121 | 122 | def marge(self,dst_path): 123 | '''合并数据,合并的路径不能与当前使用的路径相同,原有数据不能被删除''' 124 | shot_num = self.curr_active 125 | marge_bitcask = Bitcask(self.THRESHOLD,dst_path) 126 | 127 | for key in self.list_keys(): 128 | info = self.TABLE.get(key) 129 | 130 | file_num = int(info[0].replace(".sst",'').replace(self.path,'')) 131 | if file_num < shot_num: 132 | value = self.get(key) 133 | marge_bitcask.put(key,value) 134 | def marge2(self): 135 | '''合并数据文件,原有数据文件会被删除并重新生成''' 136 | tmp_path=self.path+"/_marge_tmp/" 137 | while(os.path.isdir(tmp_path)): 138 | tmp_path +="_marge_tmp/" 139 | 140 | os.makedirs(tmp_path) 141 | 142 | shot_num = self.curr_active 143 | marge_bitcask = Bitcask(self.THRESHOLD,tmp_path) 144 | 145 | for key in self.list_keys(): 146 | info = self.TABLE.get(key) 147 | 148 | file_num = int(info[0].replace(".sst",'').replace(self.path,'')) 149 | if file_num < shot_num: 150 | value = self.get(key) 151 | marge_bitcask.put(key,value) 152 | 153 | for i in glob(self.path+"*.sst"): 154 | old_file_num = int(i.replace(".sst",'').replace(self.path,'')) 155 | 156 | if old_file_num < shot_num: 157 | os.remove(i) 158 | 159 | for i in glob(tmp_path+"*.sst"): 160 | shutil.move(i,self.path) 161 | 162 | os.rmdir(tmp_path) 163 | 164 | ############################################# 165 | ## load or marge with hint file 166 | ############################################# 167 | def load_data_with_hint(self,path=None): 168 | '''使用线索文件加载数据文件,数据文件和线索文件应在同一个文件夹路径path中''' 169 | if path is not None: 170 | self.path = path 171 | for filename in glob(self.path+"*.hit"): 172 | self.load_file_with_hint(filename) 173 | def load_file_with_hint(self,hintfilename): 174 | '''使用线索文件加载数据文件''' 175 | f = open(hintfilename) 176 | data = f.read() 177 | list_items = data.split("t.") 178 | 179 | datafilename = hintfilename.replace("hit","sst") 180 | for item in list_items[:-1]: 181 | s= item+"t." 182 | record = pickle.loads(s) 183 | print "hint:",record 184 | if self.TABLE.has_key(record[4]) is True: 185 | ts1 = record[0] 186 | ts2 = self.__get_record(record[4])[0] 187 | if ts1 > ts2: 188 | self.TABLE[record[4]]=(datafilename,record[3],record[2]) 189 | else: 190 | self.TABLE[record[4]]=(datafilename,record[3],record[2]) 191 | f.close() 192 | def marge_with_hint(self,dst_path): 193 | '''合并数据文件时同时生成线索文件''' 194 | shot_num = self.curr_active 195 | marge_bitcask = Bitcask(self.THRESHOLD,dst_path) 196 | 197 | for key in self.list_keys(): 198 | info = self.TABLE.get(key) 199 | 200 | file_num = int(info[0].replace(".sst",'').replace(self.path,'')) 201 | if file_num < shot_num: 202 | value = self.get(key) 203 | marge_bitcask.put(key,value) 204 | 205 | info = marge_bitcask.TABLE.get(key) 206 | marge_bitcask.__put_hint(key,info[1],info[2]) 207 | def __io_write_hint(self,ts, key_size, value_size, value,key): 208 | '''将线索记录写入线索文件''' 209 | active_hintfile = '%s%s.hit' %(self.path,self.curr_active) 210 | print "hint_w:",ts,key_size,value_size,value,key 211 | with open(active_hintfile, 'a') as f: 212 | data = pickle.dumps((ts, key_size, value_size, value,key)) 213 | start = f.tell() 214 | length = len(data) 215 | f.write(data) 216 | return active_hintfile, start, length 217 | def __put_hint(self,key,value_pos,value_size): 218 | '''将线索记录写入线索文件''' 219 | key_size = len(key) 220 | ts = datetime.now() 221 | 222 | info = self.__io_write_hint(ts, key_size, value_size, value_pos,key) 223 | return True 224 | 225 | if __name__ == '__main__': 226 | # bitcask = Bitcask() 227 | # bitcask.load_data() 228 | # bitcask.load_data_with_hint("marge/") 229 | # print bitcask.get("test") 230 | # print bitcask.get("good") 231 | # print bitcask.list_keys() 232 | 233 | # bitcask.marge("marge/") 234 | # bitcask.marge_with_hint("marge2/") 235 | 236 | s = Bitcask() 237 | s.load_data("marge3/") 238 | s.marge2() 239 | 240 | # t = Bitcask() 241 | #t.load_data_with_hint("marge/") 242 | 243 | # print t.get("test") 244 | # print t.get("good") 245 | # print t.list_keys() 246 | -------------------------------------------------------------------------------- /Large-Scale-Distributed-Storage-System/bptree.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | #https://github.com/aholyoke/BPlusTree/blob/master/BPlusTree.py 3 | from bisect import bisect_left,bisect_right 4 | 5 | class BPTreeLeaf(object): 6 | def __init__(self,keys,next_leaf,capacity): 7 | self._keys = keys #sorted list 8 | self._next = next_leaf # next BPTreeLeaf 9 | self._capacity = capacity 10 | def find(self,key): 11 | '''返回key是否在叶子节点的keys列表中''' 12 | return key in self._keys 13 | def insert(self,key): 14 | '''插入key值到该叶子节点,不插入重复key值. 15 | 如果不分裂返回(None,None); 16 | 如果分裂,则返回(pkey,ppointer),代表需要提升的key值和新创建的叶子节点''' 17 | index = bisect_left(self._keys,key) 18 | 19 | if index == len(self._keys) or self._keys[index] != key: 20 | self._keys.insert(index,key) 21 | 22 | cap = self._capacity 23 | split_index = (cap+1)//2 24 | 25 | if len(self._keys) > cap: 26 | new_leaf = BPTreeLeaf(self._keys[split_index:],self._next,cap) 27 | 28 | self._keys = self._keys[:split_index] 29 | self._next = new_leaf 30 | 31 | return (new_leaf._keys[0],new_leaf) 32 | return (None,None) 33 | def num_nodes(self): 34 | return 0 35 | def num_leaves(self): 36 | return 1 37 | def num_keys(self): 38 | return len(self._keys) 39 | def height(self): 40 | return 0 41 | def __str__(self): 42 | return str(self._keys) 43 | class BPTreeNode(object): 44 | def __init__(self,keys,pointers,capacity): 45 | '''新建一个非叶子节点,keys = [key0,key1,...keyN],pointers = [pointer1,pointer2,...pointerN+1]''' 46 | self._keys = keys 47 | self._pointers = pointers 48 | self._capacity = capacity 49 | def find(self,key): 50 | '''返回key值是否在这个子树的叶子节点中''' 51 | return self._pointers[bisect_right(self._keys,key)].find(key) 52 | def insert_here(self,pos,key,pointer): 53 | '''将key 插入在位置pos,pointer插入在位置pos+1 54 | 如果不分裂,返回(None,None) 55 | 如果分裂,返回(pkey,ppointer),代表被提升的key和指向新创建的BPTreeNode的指针 56 | ''' 57 | self._keys.insert(pos,key) 58 | self._pointers.insert(pos+1,pointer) 59 | 60 | cap = self._capacity 61 | split_index = (cap+1)//2 62 | 63 | if len(self._keys) > cap: 64 | pkey = self._keys[split_index] 65 | self._keys.remove(pkey) 66 | 67 | new_node = BPTreeNode(self._keys[split_index:],self._pointers[split_index+1:],cap) 68 | 69 | self._keys = self._keys[:split_index] 70 | self._pointers = self._pointers[:split_index+1] 71 | 72 | return (pkey,new_node) 73 | return (None,None) 74 | def insert(self,key): 75 | '''将key插入该子树 76 | 如果没有分裂,返回(None,None) 77 | 如何分裂,返回(pkey,ppointer)''' 78 | 79 | pkey,ppointer = self._pointers[bisect_right(self._keys,key)].insert(key) 80 | 81 | if pkey is not None: 82 | pos = bisect_left (self._keys,key) 83 | promoted_key,new_node = self.insert_here(pos,pkey,ppointer) 84 | return (promoted_key,new_node) 85 | return (None,None) 86 | def height(self): 87 | return 1 + self._pointers[0].height() 88 | def num_keys(self): 89 | return sum(map(lambda n:n.num_keys(),self._pointers)) 90 | def num_leaves(self): 91 | return sum(map(lambda n: n.num_leaves(),self._pointers)) 92 | def __str__(self): 93 | return str(self._keys) 94 | 95 | class BPTree(object): 96 | def __init__(self,capacity): 97 | self._tree = BPTreeLeaf([],None,capacity) 98 | self._capacity = capacity 99 | def insert(self,key): 100 | pkey,ppointer = self._tree.insert(key) 101 | if pkey is not None: 102 | new_node = BPTreeNode([pkey],[self._tree,ppointer],self._capacity) 103 | self._tree = new_node 104 | def find(self,key): 105 | return self._tree.find(key) 106 | def height(self): 107 | return self._tree.height()+1 108 | def num_keys(self): 109 | return self._tree.num_keys() 110 | def __str__(self): 111 | s = "" 112 | stack = [] 113 | 114 | for level in range(1, self.height() + 1): 115 | s +="level [%d]:"%level 116 | if level == 1: 117 | s += str(self._tree) 118 | stack.append(self._tree) 119 | elif level == self.height(): 120 | 121 | leaf = self._tree._pointers[0] 122 | for i in range(self.height()-2): 123 | leaf = leaf._pointers[0] 124 | 125 | while leaf._next is not None: 126 | s += str(leaf)+"->" 127 | leaf = leaf._next 128 | s += str(leaf) 129 | else: 130 | child_stack = [] 131 | while len(stack) > 0: 132 | for child in stack.pop()._pointers: 133 | s+= str(child) + " " 134 | child_stack.append(child) 135 | stack = child_stack 136 | 137 | s += "\n" 138 | return s 139 | 140 | def LeafTest(): 141 | a = BPTreeLeaf([1,4,7],None,4) 142 | pkey,ppointer = a.insert(5) 143 | print pkey,ppointer 144 | print a,ppointer #[1, 4, 5, 7] None 145 | pkey,ppointer = a.insert(6) 146 | print pkey,ppointer 147 | print a,ppointer #[1, 4] [5, 6, 7] 148 | def NodeTest(): 149 | l1 = BPTreeLeaf([1,3],None,2) 150 | l2 = BPTreeLeaf([5,6],None,2) 151 | b = BPTreeNode([4],[l1,l2],2) 152 | print b 153 | print b.insert(9) 154 | print b.find(9) 155 | for i in b._pointers: 156 | print i, 157 | def TreeTest(): 158 | b = BPTree(2) 159 | b.insert(1) 160 | b.insert(3) 161 | b.insert(2) 162 | b.insert(4) 163 | b.insert(5) 164 | 165 | print b 166 | 167 | if __name__ == '__main__': 168 | #LeafTest() 169 | #NodeTest() 170 | TreeTest() 171 | -------------------------------------------------------------------------------- /Large-Scale-Distributed-Storage-System/lsm_tree.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os 4 | import shutil 5 | import skiplist 6 | import cPickle as pickle 7 | from glob import glob 8 | from binascii import crc32 9 | from datetime import datetime 10 | 11 | class KVTuple(object): 12 | '''at least define __lt__ and __eq__''' 13 | def __init__(self,key,value): 14 | self.key = key 15 | self.value = value 16 | def __eq__(self,other): 17 | return self.key == other.key 18 | def __lt__(self,other): 19 | return self.key < other.key 20 | def __repr__(self): 21 | return "(%s:%s)"%(str(self.key),str(self.value)) 22 | 23 | class LSMTree(object): 24 | def __init__(self,THRESHOLD=10000,path="./"): 25 | self.TABLE = skiplist.SkipList(isdup=False) 26 | self.THRESHOLD = THRESHOLD 27 | self.path = path 28 | self.curr_active = max([int(f.replace('.sst', '').replace(self.path,'')) for f in glob(path+'*.sst')] or [1]) 29 | 30 | if os.path.exists(path) == False: 31 | shutil.mkdir(path) 32 | 33 | def get(self,key): 34 | '''根据Key获取对应的值''' 35 | record = self.__get_record(key) 36 | if record != None: 37 | return record[5] 38 | return None 39 | 40 | def put(self,key, value): 41 | '''将key,value写入数据文件''' 42 | key_size = len(key) 43 | 44 | value_size = 0 45 | if value is not None: 46 | value_size = len(value) 47 | 48 | ts = datetime.now() 49 | crc = crc32('{0}{1}{2}{3}{4}'.format( 50 | ts, key_size, value_size, key, value)) 51 | info = self.__io_write(crc, ts, key_size, value_size, key, value) 52 | self.TABLE.insert(KVTuple(key,info)) 53 | return True 54 | 55 | def delete(self,key): 56 | '''删除Key对应的记录''' 57 | return self.put(key,None) 58 | def update(self,key): 59 | '''更新Key对应的记录''' 60 | return self.put(key,value) 61 | 62 | 63 | def __get_record(self,key): 64 | '''根据key取出数据文件中对应的整条记录''' 65 | info = None 66 | try: 67 | info = self.TABLE.get(KVTuple(key,None)).value 68 | except: 69 | pass 70 | if not info: 71 | #read from other older data file 72 | return self.get_record_from_files(key) 73 | pickled_data = self.__io_read(*info) 74 | data = pickle.loads(pickled_data) 75 | # check tuple, crc, the same key? 76 | return data 77 | 78 | 79 | def __io_read(self,filename, start, length): 80 | '''读取未经反序列化的文件数据''' 81 | with open(filename, 'rb') as f: 82 | f.seek(start) 83 | return f.read(length) 84 | 85 | def __io_write(self,crc, ts, key_size, value_size, key, value): 86 | '''将记录序列化后写入文件''' 87 | active_filename = '%s%s.sst' %(self.path,self.curr_active) 88 | 89 | try: 90 | if os.path.getsize(active_filename) >= self.THRESHOLD: 91 | self.curr_active += 1 92 | active_filename = '%s%s.sst' % self.path,self.curr_active 93 | except: 94 | pass 95 | with open(active_filename, 'a') as f: 96 | data = pickle.dumps((crc, ts, key_size, value_size, key, value)) 97 | start = f.tell() 98 | length = len(data) 99 | f.write(data) 100 | return active_filename, start, length 101 | 102 | 103 | def list_keys(self): 104 | '''返回所有记录的Key列表''' 105 | pass 106 | #return self.TABLE.keys() 107 | def get_record_from_files(self,key): 108 | filenums=[] 109 | for filename in glob(self.path+"*.sst"): 110 | filenum = int(filename.replace(self.path,'').replace('.sst','')) 111 | filenums.append(filenum) 112 | filenums.sort(reverse=True) 113 | for i in filenums: 114 | filename = self.path+str(i)+'.sst' 115 | record = self.get_record_from_file(key,filename) 116 | if record != None: 117 | return record 118 | return None 119 | def get_record_from_file(self,key,filename): 120 | try: 121 | f = open(filename) 122 | except: 123 | f.close() 124 | return None 125 | data = f.read() 126 | list_items = data.split("t.") 127 | 128 | records=[] 129 | for item in list_items[:-1]: 130 | s= item+"t." 131 | record = pickle.loads(s) 132 | 133 | if key == record[4]: 134 | records.append(record) 135 | f.close() 136 | if len(records) > 0: 137 | return records[len(records)-1] 138 | else: 139 | return None 140 | 141 | if __name__ == '__main__': 142 | lsm = LSMTree() 143 | # lsm.put("100","good") 144 | # lsm.put("200","cood") 145 | # lsm.put("100","xood") 146 | print lsm.TABLE 147 | print lsm.get("100") 148 | print lsm.get("200") 149 | 150 | -------------------------------------------------------------------------------- /Large-Scale-Distributed-Storage-System/skiplist.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | class SkipNode: 4 | def __init__(self, level, val): 5 | self.value = val 6 | self.forward = [None]*(level+1) # array of pointerS 7 | 8 | class SkipList: 9 | 10 | # initializer 11 | def __init__(self,max_level=16,prob = 0.5,isdup = True): 12 | self.MAX_LEVEL = max_level 13 | self.p = prob 14 | self.isdup = isdup 15 | self.level = 0 16 | self.head = SkipNode(self.MAX_LEVEL, None) 17 | # print method 18 | def __repr__(self): 19 | curr = self.head.forward[0] 20 | pstring = "{" 21 | 22 | while curr != None: 23 | pstring += str(curr.value) 24 | 25 | curr = curr.forward[0] 26 | if curr != None: 27 | pstring += ", " 28 | 29 | return pstring + "}" 30 | 31 | # contains: returns true if value is contained in the list 32 | def find(self, value): 33 | curr = self.head 34 | for i in range(self.level, -1, -1): 35 | while curr.forward[i] != None and curr.forward[i].value < value: 36 | curr = curr.forward[i] 37 | curr = curr.forward[0] 38 | 39 | return curr != None and curr.value == value 40 | 41 | # find and record traversal update[i] 42 | # returns update[] and insertion/deletion point 43 | def findandupdate(self, value): 44 | update = [None]*(self.MAX_LEVEL+1) 45 | curr = self.head 46 | 47 | for i in range(self.MAX_LEVEL, -1, -1): 48 | while curr.forward[i] != None and curr.forward[i].value < value: 49 | curr = curr.forward[i] 50 | update[i] = curr 51 | 52 | return (curr.forward[0], update) 53 | 54 | 55 | # insert method 56 | def insert(self, value): 57 | curr, update = self.findandupdate(value) 58 | 59 | # 60 | if self.isdup is False: 61 | if curr != None and curr.value == value: 62 | return 63 | 64 | newlevel = self.randomlevel() 65 | 66 | if newlevel > self.level: 67 | for i in range(self.level+1, newlevel+1): 68 | update[i] = self.head 69 | 70 | self.level = newlevel 71 | 72 | newnode = SkipNode(newlevel, value) 73 | 74 | for i in range(0, newlevel+1): 75 | newnode.forward[i] = update[i].forward[i] 76 | update[i].forward[i] = newnode 77 | 78 | # deletemethod 79 | def delete(self, value): 80 | curr, update = self.findandupdate(value) 81 | 82 | if curr != None and curr.value == value: 83 | # found it. Remove from list 84 | for i in range(0, self.level+1): 85 | if update[i].forward[i] != curr: 86 | break 87 | update[i].forward[i] = curr.forward[i] 88 | 89 | # decrease list level if the node deleted 90 | # had the highest level in the skip list 91 | while self.level > 0 and self.head.forward[self.level] == None: 92 | self.level -= 1 93 | 94 | """ 95 | randomlevel: 96 | random level generator for skip list node 97 | """ 98 | def randomlevel(self): 99 | level = 1 100 | while random.random() < self.p and level < self.MAX_LEVEL: 101 | level = level + 1 102 | return level 103 | 104 | if __name__ == "__main__": 105 | s = SkipList(isdup=False) 106 | 107 | s.insert(100) 108 | s.insert(200) 109 | s.insert(100) 110 | s.insert(200) 111 | 112 | s.delete(100) 113 | print s.find(100) 114 | print s.find(200) 115 | print s 116 | 117 | -------------------------------------------------------------------------------- /Large-Scale-Distributed-Storage-System/skiplist/makefile: -------------------------------------------------------------------------------- 1 | CC=g++ 2 | GTEST_CPPFLAGS=-I/usr/include -pthread 3 | GTEST_LDFLAGS=-L/usr/lib64 -lgtest -pthread 4 | 5 | CPPFLAGS=-Isrc/ 6 | all: testcase 7 | 8 | testcase: 9 | $(CC) $(GTEST_CPPFLAGS) $(CPPFLAGS) -g -c test/skiplist_test.cpp 10 | $(CC) $(GTEST_LDFLAGS) -g -o testcase skiplist_test.o 11 | clean: 12 | rm -f *.o testcase 13 | -------------------------------------------------------------------------------- /Large-Scale-Distributed-Storage-System/skiplist/src/skiplist.cpp: -------------------------------------------------------------------------------- 1 | #ifndef _SKIPLIST_H 2 | #define _SKIPLIST_H 3 | 4 | #include 5 | template class SkipList_traits; 6 | 7 | template 8 | struct SkipList_traits{ 9 | typedef const T * const_value_type; 10 | }; 11 | 12 | template 13 | struct SkipList_traits{ 14 | typedef const T * const const_value_type; 15 | }; 16 | template<> 17 | struct SkipList_traits{ 18 | typedef const int const_value_type; 19 | }; 20 | 21 | template 22 | class SkipList 23 | { 24 | public: 25 | typedef typename SkipList_traits::const_value_type const_value_type; 26 | public: 27 | 28 | SkipList(); 29 | ~SkipList(); 30 | 31 | bool find(const_value_type &value) const; 32 | bool insert(const_value_type &value); 33 | void remove(const_value_type &value); 34 | 35 | //for deubug 36 | void print(); 37 | 38 | unsigned long size() const{return m_size;} 39 | unsigned int level() const{return m_level;} 40 | unsigned int maxlevel() const{return MAXLEVEL;} 41 | protected: 42 | unsigned int randlevel() const; 43 | protected: 44 | typedef struct SkipListNode 45 | { 46 | type value; 47 | struct skiplistLevel { 48 | struct SkipListNode *forward; 49 | }level[MAXLEVEL]; 50 | 51 | SkipListNode() 52 | { 53 | for( int i = 0; i < MAXLEVEL; ++i){ 54 | level[i].forward = NULL; 55 | } 56 | } 57 | }SkipListNode; 58 | 59 | SkipListNode *head; 60 | private: 61 | unsigned int m_level; 62 | unsigned long m_size; 63 | }; 64 | 65 | #include "skiplist.cpp" //!! importent,you shouldn't delete it 66 | 67 | #endif 68 | cxy-/home/chenxueyou/skiplist/src$ cat skiplist.cpp 69 | #ifndef _SKIPLIST_CPP 70 | #define _SKIPLIST_CPP 71 | 72 | #include "skiplist.h" 73 | #include 74 | #include 75 | #include 76 | 77 | 78 | template 79 | SkipList::SkipList() 80 | :m_size(0),m_level(1) 81 | { 82 | srand((unsigned int)(time(NULL))); 83 | 84 | head = new SkipListNode; 85 | 86 | } 87 | 88 | template 89 | SkipList::~SkipList() 90 | { 91 | SkipListNode *node = head->level[0].forward; 92 | SkipListNode *next = NULL; 93 | 94 | delete head; 95 | 96 | while(node != NULL){ 97 | next = node->level[0].forward; 98 | delete node; 99 | node = next; 100 | } 101 | } 102 | 103 | template 104 | bool SkipList::find(const_value_type &value) const 105 | { 106 | SkipListNode *node = head; 107 | 108 | for(int i = m_level - 1; i >= 0 ; --i){ 109 | while(node->level[i].forward && node->level[i].forward->value < value){ 110 | node = node->level[i].forward; 111 | } 112 | } 113 | node = node->level[0].forward; 114 | 115 | if(node != NULL && node->value == value){ 116 | return true; 117 | } 118 | 119 | return false; 120 | } 121 | 122 | template 123 | bool SkipList::insert(const_value_type &value) 124 | { 125 | SkipListNode *update[MAXLEVEL]; 126 | SkipListNode *node; 127 | 128 | node = head; 129 | for(int i = m_level - 1; i >= 0 ; --i){ 130 | while(node->level[i].forward && node->level[i].forward->value < value){ 131 | node = node->level[i].forward; 132 | } 133 | update[i] = node; 134 | } 135 | 136 | int level = randlevel(); 137 | 138 | if( level > m_level){ 139 | for(int i = m_level; i < level; ++i){ 140 | update[i] = head; 141 | } 142 | 143 | m_level = level; 144 | } 145 | 146 | node = new SkipListNode(); 147 | 148 | node->value = value; 149 | 150 | for(int i = 0; i < m_level; ++i){ 151 | node->level[i].forward = update[i]->level[i].forward; 152 | update[i]->level[i].forward = node; 153 | } 154 | 155 | m_size++; 156 | 157 | return true; 158 | } 159 | 160 | template 161 | void SkipList::remove(const_value_type &value) 162 | { 163 | SkipListNode *update[MAXLEVEL]; 164 | SkipListNode *node = head; 165 | 166 | for(int i = MAXLEVEL; i >= 0; --i){ 167 | while(node->level[i].forward && node->level[i].forward->value < value){ 168 | node = node->level[i].forward; 169 | } 170 | 171 | update[i] = node; 172 | } 173 | 174 | node = node->level[0].forward; 175 | 176 | if(node && node->value == value){ 177 | for(int i = 0; i < m_level ; ++i){ 178 | update[i]->level[i].forward = node->level[i].forward; 179 | } 180 | while(m+level > 1 && head->level[m_level -1].forward == NULL){ 181 | m_level--; 182 | } 183 | delete node; 184 | m_size--; 185 | } 186 | } 187 | 188 | template 189 | void SkipList::print() 190 | { 191 | SkipListNode *node = NULL; 192 | 193 | for(int i = MAXLEVEL - 1 ; i >= 0 ; --i){ 194 | printf("LEVEL[%d]:",i); 195 | 196 | node = head->level[i].forward; 197 | 198 | while(node != NULL){ 199 | std::cout<value<<" -> "; 200 | node = node->level[i].forward; 201 | } 202 | 203 | printf("NULL\n"); 204 | } 205 | } 206 | 207 | // determine a random level for a new node, 208 | // a 1/2 chance it will be a single level, 209 | // 1/4 chance it will be two levels, 210 | // 1/8 chance it will be three levels, 211 | // etc 212 | template 213 | unsigned int SkipList::randlevel() const 214 | { 215 | for (int i = 0; i < MAXLEVEL; i++) { 216 | if ((rand()%2) == 0) 217 | return i; 218 | } 219 | return (MAXLEVEL - 1); 220 | } 221 | 222 | #endif 223 | 224 | #ifdef SKIPLIST_TEST_MAIN 225 | 226 | int main() 227 | { 228 | SkipList skiplist; 229 | int s[] ={1,3,5,7,2}; 230 | 231 | for(int i = 0; i < 5; ++i){ 232 | skiplist.insert(s[i]); 233 | } 234 | 235 | skiplist.insert(10); 236 | skiplist.print(); 237 | 238 | std::cout<<"find:"< 5 | template class SkipList_traits; 6 | 7 | template 8 | struct SkipList_traits{ 9 | typedef const T * const_value_type; 10 | }; 11 | 12 | template 13 | struct SkipList_traits{ 14 | typedef const T * const const_value_type; 15 | }; 16 | template<> 17 | struct SkipList_traits{ 18 | typedef const int const_value_type; 19 | }; 20 | 21 | template 22 | class SkipList 23 | { 24 | public: 25 | typedef typename SkipList_traits::const_value_type const_value_type; 26 | public: 27 | 28 | SkipList(); 29 | ~SkipList(); 30 | 31 | bool find(const_value_type &value) const; 32 | bool insert(const_value_type &value); 33 | void remove(const_value_type &value); 34 | 35 | //for deubug 36 | void print(); 37 | 38 | unsigned long size() const{return m_size;} 39 | unsigned int level() const{return m_level;} 40 | unsigned int maxlevel() const{return MAXLEVEL;} 41 | protected: 42 | unsigned int randlevel() const; 43 | protected: 44 | typedef struct SkipListNode 45 | { 46 | type value; 47 | struct skiplistLevel { 48 | struct SkipListNode *forward; 49 | }level[MAXLEVEL]; 50 | 51 | SkipListNode() 52 | { 53 | for( int i = 0; i < MAXLEVEL; ++i){ 54 | level[i].forward = NULL; 55 | } 56 | } 57 | }SkipListNode; 58 | 59 | SkipListNode *head; 60 | private: 61 | unsigned int m_level; 62 | unsigned long m_size; 63 | }; 64 | 65 | #include "skiplist.cpp" //!! importent,you shouldn't delete it 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /Large-Scale-Distributed-Storage-System/skiplist/test/skiplist_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "skiplist.h" 4 | 5 | #ifdef SKIPLIST_TEST_MAIN 6 | #undef SKIPLIST_TEST_MAIN 7 | #endif 8 | 9 | using namespace std; 10 | 11 | TEST(INIT_TEST,InitTest) 12 | { 13 | SkipList skiplist; 14 | 15 | EXPECT_EQ(skiplist.maxlevel(),8); 16 | EXPECT_EQ(skiplist.level(),1); 17 | EXPECT_EQ(skiplist.size(),0); 18 | EXPECT_EQ(skiplist.find(0),false); 19 | 20 | } 21 | 22 | TEST(INSERT_TEST,InsertTest) 23 | { 24 | SkipList skiplist; 25 | 26 | int s[]={1,5,7,2}; 27 | for(int i = 0; i < 4; ++i){ 28 | skiplist.insert(s[i]); 29 | } 30 | skiplist.insert(3); 31 | 32 | EXPECT_EQ(skiplist.size(),5); 33 | 34 | for(int i = 0; i < 4; ++i){ 35 | EXPECT_EQ(skiplist.find(s[i]),true); 36 | } 37 | EXPECT_EQ(skiplist.find(3),true); 38 | 39 | } 40 | 41 | TEST(INSERT_TEST,InsertDupTest) 42 | { 43 | SkipList skiplist; 44 | 45 | int s[]={1,5,5,2,1}; 46 | for(int i = 0; i < 5; ++i){ 47 | skiplist.insert(s[i]); 48 | } 49 | 50 | EXPECT_EQ(skiplist.size(),5); 51 | 52 | skiplist.remove(s[1]); 53 | skiplist.remove(s[4]); 54 | 55 | EXPECT_EQ(skiplist.size(),3); 56 | 57 | EXPECT_EQ(skiplist.find(s[0]),true); 58 | EXPECT_EQ(skiplist.find(s[1]),true); 59 | EXPECT_EQ(skiplist.find(s[2]),true); 60 | EXPECT_EQ(skiplist.find(s[3]),true); 61 | EXPECT_EQ(skiplist.find(s[4]),true); 62 | 63 | } 64 | 65 | TEST(DELETE_TEST,DeleteTest) 66 | { 67 | SkipList skiplist; 68 | 69 | int s[]={1,5,7,2,3}; 70 | for(int i = 0; i < 5; ++i){ 71 | skiplist.insert(s[i]); 72 | } 73 | 74 | skiplist.remove(s[1]); 75 | skiplist.remove(s[4]); 76 | 77 | EXPECT_EQ(skiplist.size(),3); 78 | 79 | EXPECT_EQ(skiplist.find(s[0]),true); 80 | EXPECT_EQ(skiplist.find(s[1]),false); 81 | EXPECT_EQ(skiplist.find(s[2]),true); 82 | EXPECT_EQ(skiplist.find(s[3]),true); 83 | EXPECT_EQ(skiplist.find(s[4]),false); 84 | 85 | } 86 | 87 | TEST(DELETE_TEST,DeleteDupTest) 88 | { 89 | SkipList skiplist; 90 | 91 | int s[]={1,5,7,2,3}; 92 | for(int i = 0; i < 5; ++i){ 93 | skiplist.insert(s[i]); 94 | } 95 | 96 | skiplist.remove(s[0]); 97 | skiplist.remove(s[0]); 98 | 99 | EXPECT_EQ(skiplist.size(),4); 100 | 101 | EXPECT_EQ(skiplist.find(s[0]),false); 102 | EXPECT_EQ(skiplist.find(s[1]),true); 103 | EXPECT_EQ(skiplist.find(s[2]),true); 104 | EXPECT_EQ(skiplist.find(s[3]),true); 105 | EXPECT_EQ(skiplist.find(s[4]),true); 106 | 107 | } 108 | 109 | TEST(DELETE_TEST,DeleteAllTest) 110 | { 111 | SkipList skiplist; 112 | 113 | int s[]={1,5,7,2,3}; 114 | for(int i = 0; i < 5; ++i){ 115 | skiplist.insert(s[i]); 116 | } 117 | 118 | for(int i = 0; i < 5; ++i){ 119 | skiplist.remove(s[i]); 120 | } 121 | 122 | EXPECT_EQ(skiplist.size(),0); 123 | 124 | EXPECT_EQ(skiplist.find(s[0]),false); 125 | EXPECT_EQ(skiplist.find(s[1]),false); 126 | EXPECT_EQ(skiplist.find(s[2]),false); 127 | EXPECT_EQ(skiplist.find(s[3]),false); 128 | EXPECT_EQ(skiplist.find(s[4]),false); 129 | 130 | } 131 | 132 | int main(int argc, char* argv[]) 133 | { 134 | testing::InitGoogleTest(&argc, argv); 135 | return RUN_ALL_TESTS(); 136 | } 137 | -------------------------------------------------------------------------------- /Large-Scale-Distributed-Storage-System/skiplist0.2/Readme.md: -------------------------------------------------------------------------------- 1 | 增加了迭代器,可以使用begin,end等迭代器函数 2 | -------------------------------------------------------------------------------- /Large-Scale-Distributed-Storage-System/skiplist0.2/makefile: -------------------------------------------------------------------------------- 1 | 2 | CC=g++ 3 | GTEST_CPPFLAGS=-I/usr/include -pthread 4 | GTEST_LDFLAGS=-L/usr/lib64 -lgtest -pthread 5 | 6 | CPPFLAGS=-Isrc/ 7 | all: testcase 8 | 9 | testcase: 10 | $(CC) $(GTEST_CPPFLAGS) $(CPPFLAGS) -g -c test/skiplist_test.cpp 11 | $(CC) $(GTEST_LDFLAGS) -g -o testcase skiplist_test.o 12 | clean: 13 | rm -f *.o testcase 14 | 15 | 16 | 17 | 18 | # g++ $(gtest-config --cppflags --cxxflags) -o $(TARGET).o -c test_main.cpp 19 | # g++ $(gtest-config --ldflags --libs) -o $(TARGET) $(TARGET).o 20 | -------------------------------------------------------------------------------- /Large-Scale-Distributed-Storage-System/skiplist0.2/src/skiplist.cpp: -------------------------------------------------------------------------------- 1 | #ifndef _SKIPLIST_CPP 2 | #define _SKIPLIST_CPP 3 | 4 | #include "skiplist.h" 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace skiplist; 10 | 11 | template 12 | SkipList::SkipList() 13 | :size_(0),level_(1),tail(NULL) 14 | { 15 | srand((unsigned int)(time(NULL))); 16 | 17 | head = new node_t; 18 | 19 | } 20 | 21 | template 22 | SkipList::~SkipList() 23 | { 24 | node_t *node = head->level[0].forward; 25 | node_t *next = NULL; 26 | 27 | delete head; 28 | 29 | while(node != NULL){ 30 | next = node->level[0].forward; 31 | delete node; 32 | node = next; 33 | } 34 | } 35 | 36 | 37 | template 38 | void SkipList::insert(const_value_type &value) 39 | { 40 | node_t *update[MAXLEVEL]; 41 | node_t *node; 42 | 43 | node = head; 44 | for(int i = level_ - 1; i >= 0 ; --i){ 45 | while(node->level[i].forward && node->level[i].forward->value < value){ 46 | node = node->level[i].forward; 47 | } 48 | update[i] = node; 49 | } 50 | 51 | int level = randlevel(); 52 | 53 | if( level > level_){ 54 | for(int i = level_; i < level; ++i){ 55 | update[i] = head; 56 | } 57 | 58 | level_ = level; 59 | } 60 | 61 | node = new node_t(); 62 | 63 | node->value = value; 64 | 65 | for(int i = 0; i < level_; ++i){ 66 | node->level[i].forward = update[i]->level[i].forward; 67 | update[i]->level[i].forward = node; 68 | } 69 | 70 | node->backward = (update[0] == head ? NULL:update[0]); 71 | if(node->level[0].forward != NULL){ 72 | node->level[0].forward->backward = node; 73 | }else{ 74 | tail = node; 75 | } 76 | size_++; 77 | 78 | } 79 | 80 | template 81 | void SkipList::remove(const_value_type &value) 82 | { 83 | node_t *update[MAXLEVEL]={NULL}; 84 | node_t *node = head; 85 | 86 | for(int i = MAXLEVEL - 1; i >= 0; --i){ 87 | while(node->level[i].forward && node->level[i].forward->value < value){ 88 | node = node->level[i].forward; 89 | } 90 | 91 | update[i] = node; 92 | } 93 | 94 | node = node->level[0].forward; 95 | 96 | if(node && node->value == value){ 97 | for(int i = 0; i < level_ ; ++i){ 98 | if(update[i]->level[i].forward == node){ 99 | update[i]->level[i].forward = node->level[i].forward; 100 | } 101 | } 102 | 103 | if(node->level[0].forward != NULL){ 104 | node->level[0].forward->backward = node->backward; 105 | }else{ 106 | tail = node->backward; 107 | } 108 | 109 | while(level_ > 1 && head->level[level_ -1].forward == NULL){ 110 | level_--; 111 | } 112 | delete node; 113 | size_--; 114 | } 115 | } 116 | 117 | template 118 | void SkipList::clear() 119 | { 120 | node_t *node = head->level[0].forward; 121 | node_t *next = NULL; 122 | 123 | while(node != NULL){ 124 | next = node->level[0].forward; 125 | delete node; 126 | node = next; 127 | } 128 | 129 | for(int i = level_ - 1; i >= 0 ; --i){ 130 | head->level[i].forward = NULL; 131 | } 132 | 133 | size_ = 0; 134 | level_ = 1; 135 | tail = NULL; 136 | } 137 | 138 | template 139 | void SkipList::print() 140 | { 141 | node_t *node = NULL; 142 | 143 | for(int i = MAXLEVEL - 1 ; i >= 0 ; --i){ 144 | printf("LEVEL[%d]:",i); 145 | 146 | node = head->level[i].forward; 147 | 148 | while(node != NULL){ 149 | std::cout<value<<" -> "; 150 | node = node->level[i].forward; 151 | } 152 | 153 | printf("NULL\n"); 154 | } 155 | } 156 | 157 | // determine a random level for a new node, 158 | // a 1/2 chance it will be a single level, 159 | // 1/4 chance it will be two levels, 160 | // 1/8 chance it will be three levels, 161 | // etc 162 | template 163 | unsigned int SkipList::randlevel() const 164 | { 165 | for (int i = 0; i < MAXLEVEL; i++) { 166 | if ((rand()%2) == 0) 167 | return i; 168 | } 169 | return (MAXLEVEL - 1); 170 | } 171 | 172 | #endif 173 | 174 | #ifdef SKIPLIST_TEST_MAIN 175 | 176 | int main() 177 | { 178 | SkipList skiplist; 179 | int s[] ={1,3,5,7,2}; 180 | 181 | for(int i = 0; i < 5; ++i){ 182 | skiplist.insert(s[i]); 183 | } 184 | 185 | skiplist.insert(10); 186 | skiplist.print(); 187 | 188 | std::cout<<"find:"< 5 | namespace skiplist{ 6 | 7 | template 8 | struct SkipListNode 9 | { 10 | typedef SkipListNode* ptr_t; 11 | typedef const SkipListNode* const_ptr_t; 12 | 13 | type value; 14 | struct SkipListNode *backward; 15 | struct skiplistLevel { 16 | struct SkipListNode *forward; 17 | }level[MAXLEVEL]; 18 | 19 | SkipListNode():backward(NULL) 20 | { 21 | for( int i = 0; i < MAXLEVEL; ++i){ 22 | level[i].forward = NULL; 23 | } 24 | } 25 | }; 26 | 27 | template 28 | class ConstIterator 29 | { 30 | typedef ConstIterator self_t; 31 | 32 | public: 33 | typedef typename List::value_type value_type; 34 | typedef typename List::const_reference reference; 35 | typedef typename List::const_pointer pointer; 36 | private: 37 | typedef typename List::iterator iterator; 38 | typedef SkipListNode node_t; 39 | typedef typename node_t::ptr_t node_ptr_t; 40 | typedef typename node_t::const_ptr_t node_const_ptr_t; 41 | public: 42 | ConstIterator():node_(NULL),level_(0) 43 | { 44 | } 45 | ConstIterator(const self_t &other) 46 | { 47 | *this = other; 48 | } 49 | self_t &operator =(const self_t &other) 50 | { 51 | node_ = other.node_; 52 | level_ = other.level_; 53 | return *this; 54 | } 55 | ConstIterator(const iterator &other) 56 | { 57 | *this = other; 58 | } 59 | self_t &operator = (const iterator &other) 60 | { 61 | node_ = other; 62 | return *this; 63 | } 64 | ConstIterator(node_ptr_t node):level_(0) 65 | { 66 | node_ = node; 67 | } 68 | ConstIterator(node_const_ptr_t node):level_(0) 69 | { 70 | node_ = const_cast(node); 71 | } 72 | public: 73 | void setlevel(int level) 74 | { 75 | level_ = level; 76 | } 77 | reference operator *() const 78 | { 79 | // NOTICE 对end的访问undefined 80 | return node_->value; 81 | } 82 | pointer operator ->() const 83 | { 84 | // NOTICE 对end的访问undefined 85 | return &(node_->value); 86 | } 87 | bool operator ==(const self_t &other) const 88 | { 89 | return (node_ == other.node_); 90 | } 91 | bool operator !=(const self_t &other) const 92 | { 93 | return (node_ != other.node_); 94 | } 95 | self_t &operator ++() 96 | { 97 | node_ = node_->level[level_].forward; 98 | return *this; 99 | } 100 | 101 | self_t operator ++(int ) 102 | { 103 | self_t tmp = *this; 104 | 105 | node_ = node_->level[level_].forward; 106 | 107 | return tmp; 108 | } 109 | self_t &operator --() 110 | { 111 | node_ = node_->backward; 112 | return *this; 113 | } 114 | 115 | self_t operator --(int ) 116 | { 117 | self_t tmp = *this; 118 | 119 | node_ = node_->backward; 120 | 121 | return tmp; 122 | } 123 | private: 124 | node_ptr_t node_; 125 | int level_; 126 | }; 127 | 128 | template 129 | class Iterator 130 | { 131 | typedef Iterator self_t; 132 | 133 | public: 134 | typedef typename List::value_type value_type; 135 | typedef typename List::const_reference reference; 136 | typedef typename List::const_pointer pointer; 137 | private: 138 | typedef typename List::iterator iterator; 139 | typedef SkipListNode node_t; 140 | typedef typename node_t::ptr_t node_ptr_t; 141 | typedef typename node_t::const_ptr_t node_const_ptr_t; 142 | public: 143 | Iterator():node_(NULL),level_(0) 144 | { 145 | } 146 | Iterator(const self_t &other) 147 | { 148 | *this = other; 149 | } 150 | self_t &operator =(const self_t &other) 151 | { 152 | node_ = other.node_; 153 | level_ = other.level_; 154 | return *this; 155 | } 156 | Iterator(node_ptr_t node):level_(0) 157 | { 158 | node_ = node; 159 | } 160 | Iterator(node_const_ptr_t node):level_(0) 161 | { 162 | node_ = const_cast(node); 163 | } 164 | public: 165 | void setlevel(int level) 166 | { 167 | level_ = level; 168 | } 169 | reference operator *() const 170 | { 171 | // NOTICE 对end的访问undefined 172 | return node_->value; 173 | } 174 | pointer operator ->() const 175 | { 176 | // NOTICE 对end的访问undefined 177 | return &(node_->value); 178 | } 179 | bool operator ==(const self_t &other) const 180 | { 181 | return (node_ == other.node_); 182 | } 183 | bool operator !=(const self_t &other) const 184 | { 185 | return (node_ != other.node_); 186 | } 187 | self_t &operator ++() 188 | { 189 | node_ = node_->level[level_].forward; 190 | 191 | return *this; 192 | } 193 | self_t operator ++(int ) 194 | { 195 | self_t tmp = *this; 196 | node_ = node_->level[level_].forward; 197 | return tmp; 198 | } 199 | self_t &operator --() 200 | { 201 | node_ = node_->backward; 202 | return *this; 203 | } 204 | 205 | self_t operator --(int ) 206 | { 207 | self_t tmp = *this; 208 | 209 | node_ = node_->backward; 210 | 211 | return tmp; 212 | } 213 | private: 214 | node_ptr_t node_; 215 | int level_; 216 | }; 217 | 218 | 219 | 220 | //////////////////////////////////// 221 | template class SkipList_traits; 222 | 223 | 224 | 225 | template 226 | struct SkipList_traits{ 227 | typedef T pointee_type; 228 | typedef T * value_type; 229 | typedef const T * const_value_type; 230 | typedef value_type* iterator; 231 | typedef const value_type* const_iterator; 232 | typedef int difference_type; 233 | 234 | }; 235 | 236 | template 237 | struct SkipList_traits{ 238 | typedef T pointee_type; 239 | typedef const T* value_type; 240 | typedef const T* const const_value_type; 241 | typedef value_type* iterator; 242 | typedef const value_type* const_iterator; 243 | typedef int difference_type; 244 | }; 245 | template<> 246 | struct SkipList_traits{ 247 | typedef int& pointee_type; 248 | typedef int value_type; 249 | typedef const int const_value_type; 250 | typedef value_type* iterator; 251 | typedef const value_type* const_iterator; 252 | typedef int difference_type; 253 | }; 254 | 255 | template 256 | class SkipList 257 | { 258 | typedef SkipList self_t; 259 | public: 260 | typedef typename SkipList_traits::pointee_type pointee_type; 261 | typedef typename SkipList_traits::value_type value_type; 262 | typedef typename SkipList_traits::const_value_type const_value_type; 263 | typedef Iterator iterator; 264 | typedef ConstIterator const_iterator; 265 | typedef typename SkipList_traits::difference_type difference_type; 266 | typedef value_type& reference; 267 | typedef const value_type& const_reference; 268 | typedef value_type* pointer; 269 | typedef const value_type* const_pointer; 270 | typedef SkipListNode node_t; 271 | public: 272 | 273 | SkipList(); 274 | ~SkipList(); 275 | 276 | void insert(const_value_type &value); 277 | void remove(const_value_type &value); 278 | void clear(); 279 | 280 | 281 | iterator find(const_value_type &value) 282 | { 283 | node_t *node = head; 284 | 285 | for(int i = level_ - 1; i >= 0 ; --i){ 286 | while(node->level[i].forward && node->level[i].forward->value < value){ 287 | node = node->level[i].forward; 288 | } 289 | } 290 | node = node->level[0].forward; 291 | 292 | if(node != NULL && node->value == value){ 293 | return node; 294 | } 295 | 296 | return iterator((node_t *)NULL); 297 | } 298 | 299 | iterator begin(int level = 0) 300 | { 301 | iterator ret(head->level[level].forward); 302 | ret.setlevel(level); 303 | 304 | return ret; 305 | } 306 | 307 | iterator end() const 308 | { 309 | return iterator((node_t *)NULL); 310 | } 311 | 312 | iterator rbegin() const 313 | { 314 | return tail; 315 | } 316 | 317 | iterator rend() const 318 | { 319 | return iterator((node_t *)NULL); 320 | } 321 | //for deubug 322 | void print(); 323 | 324 | unsigned long size() const{return size_;} 325 | unsigned int level() const{return level_;} 326 | unsigned int maxlevel() const{return MAXLEVEL;} 327 | bool empty() const {return (size_ == 0);} 328 | protected: 329 | unsigned int randlevel() const; 330 | protected: 331 | 332 | node_t *head,*tail; 333 | private: 334 | unsigned int level_; 335 | unsigned long size_; 336 | }; 337 | 338 | #include "skiplist.cpp" //!! importent,you shouldn't delete it 339 | }//end nameapce 340 | #endif 341 | -------------------------------------------------------------------------------- /Large-Scale-Distributed-Storage-System/skiplist0.2/test/skiplist_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "skiplist.h" 4 | 5 | #ifdef SKIPLIST_TEST_MAIN 6 | #undef SKIPLIST_TEST_MAIN 7 | #endif 8 | 9 | using namespace std; 10 | using namespace skiplist; 11 | 12 | TEST(INIT_TEST,InitTest) 13 | { 14 | SkipList skiplist; 15 | 16 | EXPECT_EQ(skiplist.maxlevel(),16); 17 | EXPECT_EQ(skiplist.level(),1); 18 | EXPECT_EQ(skiplist.size(),0); 19 | EXPECT_EQ(skiplist.begin(),skiplist.end()); 20 | EXPECT_EQ(skiplist.rbegin(),skiplist.rend()); 21 | EXPECT_EQ(skiplist.find(0),skiplist.end()); 22 | 23 | } 24 | 25 | TEST(INSERT_TEST,InsertTest) 26 | { 27 | SkipList skiplist; 28 | 29 | int s[]={1,5,7,2}; 30 | for(int i = 0; i < 4; ++i){ 31 | skiplist.insert(s[i]); 32 | } 33 | skiplist.insert(3); 34 | 35 | EXPECT_EQ(skiplist.size(),5); 36 | 37 | for(int i = 0; i < 4; ++i){ 38 | EXPECT_NE(skiplist.find(s[i]),skiplist.end()); 39 | } 40 | EXPECT_NE(skiplist.find(3),skiplist.end()); 41 | 42 | } 43 | 44 | TEST(INSERT_TEST,InsertDupTest) 45 | { 46 | SkipList skiplist; 47 | 48 | int s[]={1,5,5,2,1}; 49 | for(int i = 0; i < 5; ++i){ 50 | skiplist.insert(s[i]); 51 | } 52 | 53 | EXPECT_EQ(skiplist.size(),5); 54 | 55 | skiplist.remove(s[1]); 56 | skiplist.remove(s[4]); 57 | 58 | EXPECT_EQ(skiplist.size(),3); 59 | 60 | EXPECT_NE(skiplist.find(s[0]),skiplist.end()); 61 | EXPECT_NE(skiplist.find(s[1]),skiplist.end()); 62 | EXPECT_NE(skiplist.find(s[2]),skiplist.end()); 63 | EXPECT_NE(skiplist.find(s[3]),skiplist.end()); 64 | EXPECT_NE(skiplist.find(s[4]),skiplist.end()); 65 | 66 | } 67 | 68 | TEST(DELETE_TEST,DeleteTest) 69 | { 70 | SkipList skiplist; 71 | 72 | int s[]={1,5,7,2,3}; 73 | for(int i = 0; i < 5; ++i){ 74 | skiplist.insert(s[i]); 75 | } 76 | 77 | skiplist.remove(s[1]); 78 | skiplist.remove(s[4]); 79 | 80 | EXPECT_EQ(skiplist.size(),3); 81 | 82 | EXPECT_NE(skiplist.find(s[0]),skiplist.end()); 83 | EXPECT_NE(skiplist.find(s[2]),skiplist.end()); 84 | EXPECT_NE(skiplist.find(s[3]),skiplist.end()); 85 | 86 | EXPECT_EQ(skiplist.find(s[1]),skiplist.end()); 87 | EXPECT_EQ(skiplist.find(s[4]),skiplist.end()); 88 | 89 | } 90 | 91 | TEST(DELETE_TEST,DeleteDupTest) 92 | { 93 | SkipList skiplist; 94 | 95 | int s[]={1,5,7,2,3}; 96 | for(int i = 0; i < 5; ++i){ 97 | skiplist.insert(s[i]); 98 | } 99 | 100 | skiplist.remove(s[0]); 101 | skiplist.remove(s[0]); 102 | 103 | EXPECT_EQ(skiplist.size(),4); 104 | 105 | EXPECT_NE(skiplist.find(s[1]),skiplist.end()); 106 | EXPECT_NE(skiplist.find(s[2]),skiplist.end()); 107 | EXPECT_NE(skiplist.find(s[3]),skiplist.end()); 108 | EXPECT_NE(skiplist.find(s[4]),skiplist.end()); 109 | 110 | EXPECT_EQ(skiplist.find(s[0]),skiplist.end()); 111 | } 112 | 113 | TEST(DELETE_TEST,DeleteAllTest) 114 | { 115 | SkipList skiplist; 116 | 117 | int s[]={1,5,7,2,3}; 118 | for(int i = 0; i < 5; ++i){ 119 | skiplist.insert(s[i]); 120 | } 121 | 122 | for(int i = 0; i < 5; ++i){ 123 | skiplist.remove(s[i]); 124 | } 125 | 126 | EXPECT_EQ(skiplist.size(),0); 127 | 128 | EXPECT_EQ(skiplist.find(s[0]),skiplist.end()); 129 | EXPECT_EQ(skiplist.find(s[1]),skiplist.end()); 130 | EXPECT_EQ(skiplist.find(s[2]),skiplist.end()); 131 | EXPECT_EQ(skiplist.find(s[3]),skiplist.end()); 132 | EXPECT_EQ(skiplist.find(s[4]),skiplist.end()); 133 | 134 | } 135 | TEST(ITERATOR_TEST,BeginTest) 136 | { 137 | SkipList skiplist; 138 | 139 | int s[]={4,5,7,2,3}; 140 | for(int i = 0; i < 5; ++i){ 141 | skiplist.insert(s[i]); 142 | } 143 | 144 | SkipList::iterator it=skiplist.begin(); 145 | 146 | //min value 147 | EXPECT_EQ(*it,2); 148 | 149 | } 150 | TEST(ITERATOR_TEST,IteratorTest) 151 | { 152 | SkipList skiplist; 153 | 154 | int s[]={4,5,7,2,3}; 155 | for(int i = 0; i < 5; ++i){ 156 | skiplist.insert(s[i]); 157 | } 158 | 159 | SkipList::iterator it=skiplist.begin(); 160 | 161 | //min value 162 | EXPECT_EQ(*it++,2); 163 | EXPECT_EQ(*it,3); 164 | 165 | EXPECT_EQ(*(++it),4); 166 | } 167 | TEST(ITERATOR_TEST,LevelTest) 168 | { 169 | SkipList skiplist; 170 | 171 | int s[] = {4,5,7,2,3}; 172 | for(int i = 0; i < 5; ++i){ 173 | skiplist.insert(s[i]); 174 | } 175 | 176 | if(skiplist.level() > 2){ 177 | SkipList::iterator it=skiplist.begin(); 178 | it.setlevel(2); 179 | std::cout<<"Level 2:"; 180 | for(;it != skiplist.end(); it++){ 181 | std::cout<<*it<<" "; 182 | } 183 | std::cout<<"\n"; 184 | 185 | skiplist.print(); 186 | } 187 | } 188 | 189 | TEST(ITERATOR_TEST,RangeTest) 190 | { 191 | SkipList skiplist; 192 | 193 | int s[] = {4,5,7,2,3}; 194 | for(int i = 0; i < 5; ++i){ 195 | skiplist.insert(s[i]); 196 | } 197 | 198 | SkipList::iterator it = skiplist.find(3); 199 | 200 | for(;it != skiplist.end() && (*it < 6) ; ++it){ 201 | std::cout<<*it<<" "; 202 | } 203 | std::cout< skiplist; 209 | int s[] = {1,3,5,7,9,11,13,15,17,19}; 210 | for(int i = 0; i < 10; ++i){ 211 | skiplist.insert(s[i]); 212 | } 213 | 214 | SkipList::iterator it = skiplist.rbegin(); 215 | 216 | for(int i = 10 - 1; it != skiplist.rend(); --i,++it){ 217 | EXPECT_EQ(*it,s[i]); 218 | } 219 | 220 | } 221 | int main(int argc, char* argv[]) 222 | { 223 | testing::InitGoogleTest(&argc, argv); 224 | return RUN_ALL_TESTS(); 225 | } 226 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ------ 2 | ====== 3 | --------------------------------------------------------------------------------