Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 : : /*
3 : : * Copyright 2010 Couchbase, Inc
4 : : *
5 : : * Licensed under the Apache License, Version 2.0 (the "License");
6 : : * you may not use this file except in compliance with the License.
7 : : * You may obtain a copy of the License at
8 : : *
9 : : * http://www.apache.org/licenses/LICENSE-2.0
10 : : *
11 : : * Unless required by applicable law or agreed to in writing, software
12 : : * distributed under the License is distributed on an "AS IS" BASIS,
13 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : : * See the License for the specific language governing permissions and
15 : : * limitations under the License.
16 : : */
17 : :
18 : : #include <stdio.h>
19 : : #include <stdlib.h>
20 : : #include <string.h>
21 : : #include <stdint.h>
22 : :
23 : : #include "btree.h"
24 : : #include "btree_str_kv.h"
25 : :
26 : : #include "memleak.h"
27 : :
28 : : typedef uint16_t key_len_t;
29 : :
30 : : /*
31 : : n-byte keylen vsize ...
32 : : [keylen][key ...][value][keylen][key ...][value]
33 : : */
34 : :
35 : 4 : static void _get_str_kv(struct bnode *node, idx_t idx, void *key, void *value)
36 : : {
37 : : int ksize, vsize, i;
38 : : void *key_ptr, *ptr;
39 : : key_len_t keylen, _keylen;
40 : : size_t offset;
41 : :
42 : 4 : _get_kvsize(node->kvsize, ksize, vsize);
43 : 4 : ksize = sizeof(void *);
44 : :
45 : 4 : ptr = node->data;
46 : 4 : offset = 0;
47 : : // linear search
48 [ - + ]: 4 : for (i=0;i<idx;++i){
49 : 0 : memcpy(&_keylen, (uint8_t*)ptr+offset, sizeof(key_len_t));
50 : 0 : keylen = _endian_decode(_keylen);
51 : 0 : offset += sizeof(key_len_t)+keylen + vsize;
52 : : }
53 : :
54 : : // if KEY already points to previous key, then free it
55 : 4 : memcpy(&key_ptr, key, ksize);
56 [ + + ]: 4 : if (key_ptr) {
57 : 2 : free(key_ptr);
58 : : }
59 : :
60 : : // allocate space for key
61 : 4 : memcpy(&_keylen, (uint8_t*)ptr+offset, sizeof(key_len_t));
62 : 4 : keylen = _endian_decode(_keylen);
63 : 4 : key_ptr = (void*)malloc(sizeof(key_len_t) + keylen);
64 : :
65 : : // copy key
66 : 4 : memcpy(key_ptr, &_keylen, sizeof(key_len_t));
67 : 4 : memcpy((uint8_t*)key_ptr + sizeof(key_len_t),
68 : 8 : (uint8_t*)ptr+offset+sizeof(key_len_t), keylen);
69 : : // copy key pointer
70 : 4 : memcpy(key, &key_ptr, ksize);
71 : : // copy value
72 [ + + ]: 4 : if (value) {
73 : 3 : memcpy(value, (uint8_t*)ptr + offset + sizeof(key_len_t) + keylen, vsize);
74 : : }
75 : 4 : }
76 : :
77 : 5 : static void _set_str_kv(struct bnode *node, idx_t idx, void *key, void *value)
78 : : {
79 : : int ksize, vsize, i;
80 : : void *key_ptr, *ptr;
81 : : key_len_t keylen, keylen_ins, keylen_idx;
82 : : key_len_t _keylen, _keylen_ins;
83 : : size_t offset, offset_idx, offset_next, next_len;
84 : :
85 : 5 : _get_kvsize(node->kvsize, ksize, vsize);
86 : 5 : ksize = sizeof(void *);
87 : :
88 : 5 : ptr = node->data;
89 : 5 : offset = keylen = 0;
90 : : // linear search
91 [ + + ]: 6 : for (i=0;i<idx;++i){
92 : 1 : memcpy(&_keylen, (uint8_t*)ptr+offset, sizeof(key_len_t));
93 : 1 : keylen = _endian_decode(_keylen);
94 : 1 : offset += sizeof(key_len_t)+keylen + vsize;
95 : : }
96 : 5 : offset_idx = offset;
97 : :
98 : : // copy key info from KEY
99 : 5 : memcpy(&key_ptr, key, ksize);
100 : 5 : memcpy(&_keylen_ins, key_ptr, sizeof(key_len_t));
101 : 5 : keylen_ins = _endian_decode(_keylen_ins);
102 : :
103 [ + - ][ - + ]: 5 : if (keylen_ins != keylen && idx+2 <= node->nentry) {
104 : : // we have to move idx+1 ~ nentry KVs to appropriate position
105 : 0 : next_len = 0;
106 [ # # ]: 0 : for (i=idx;i<node->nentry;++i){
107 : 0 : memcpy(&_keylen, (uint8_t*)ptr + offset, sizeof(key_len_t));
108 : 0 : keylen = _endian_decode(_keylen);
109 : :
110 [ # # ]: 0 : if (i==idx) keylen_idx = keylen;
111 [ # # ]: 0 : if (i>idx) next_len += sizeof(key_len_t) + keylen + vsize;
112 [ # # ]: 0 : if (i == idx+1) offset_next = offset;
113 : :
114 : 0 : offset += sizeof(key_len_t) + keylen + vsize;
115 : : }
116 : : // move
117 : 0 : memmove((uint8_t*)ptr + offset_next + (keylen_ins - keylen_idx),
118 : 0 : (uint8_t*)ptr + offset_next, next_len);
119 : : }
120 : :
121 : : // copy key into the node
122 : 5 : memcpy((uint8_t*)ptr + offset_idx, key_ptr, sizeof(key_len_t) + keylen_ins);
123 : : // copy value
124 : 5 : memcpy((uint8_t*)ptr + offset_idx + sizeof(key_len_t) + keylen_ins, value, vsize);
125 : 5 : }
126 : :
127 : 1 : static void _ins_str_kv(struct bnode *node, idx_t idx, void *key, void *value)
128 : : {
129 : : int ksize, vsize, i;
130 : : void *key_ptr, *ptr;
131 : : key_len_t keylen, keylen_ins;
132 : : key_len_t _keylen, _keylen_ins;
133 : 1 : size_t offset, offset_idx, offset_next = 0, next_len;
134 : :
135 : 1 : _get_kvsize(node->kvsize, ksize, vsize);
136 : 1 : ksize = sizeof(void *);
137 : :
138 : 1 : ptr = node->data;
139 : 1 : offset = 0;
140 : : // linear search
141 [ - + ]: 1 : for (i=0;i<idx;++i){
142 : 0 : memcpy(&_keylen, (uint8_t*)ptr+offset, sizeof(key_len_t));
143 : 0 : keylen = _endian_encode(_keylen);
144 : 0 : offset += sizeof(key_len_t)+keylen + vsize;
145 : : }
146 : 1 : offset_idx = offset;
147 : :
148 [ + - ][ + - ]: 1 : if (key && value) {
149 : : // insert
150 : :
151 : : // copy key info from KEY
152 : 1 : memcpy(&key_ptr, key, ksize);
153 : 1 : memcpy(&_keylen_ins, key_ptr, sizeof(key_len_t));
154 : 1 : keylen_ins = _endian_decode(_keylen_ins);
155 : :
156 : : // we have to move idx ~ nentry KVs to (next) appropriate position
157 : 1 : next_len = 0;
158 [ - + ]: 1 : for (i=idx;i<node->nentry;++i){
159 : 0 : memcpy(&_keylen, (uint8_t*)ptr + offset, sizeof(key_len_t));
160 : 0 : keylen = _endian_decode(_keylen);
161 : 0 : next_len += sizeof(key_len_t) + keylen + vsize;
162 : 0 : offset += sizeof(key_len_t) + keylen + vsize;
163 : : }
164 : :
165 : : memmove(
166 : 1 : (uint8_t*)ptr + offset_idx + sizeof(key_len_t) + keylen_ins + vsize,
167 : 2 : (uint8_t*)ptr + offset_idx, next_len);
168 : :
169 : : // copy key into the node
170 : 1 : memcpy((uint8_t*)ptr + offset_idx, key_ptr, sizeof(key_len_t) + keylen_ins);
171 : : // copy value
172 : 1 : memcpy((uint8_t*)ptr + offset_idx + sizeof(key_len_t) + keylen_ins,
173 : 1 : value, vsize);
174 : : }else{
175 : : // we have to move idx+1 ~ nentry KVs to appropriate position
176 : 0 : next_len = 0;
177 [ # # ]: 0 : for (i=idx;i<node->nentry;++i){
178 : 0 : memcpy(&_keylen, (uint8_t*)ptr + offset, sizeof(key_len_t));
179 : 0 : keylen = _endian_decode(_keylen);
180 [ # # ]: 0 : if (i>idx) next_len += sizeof(key_len_t) + keylen + vsize;
181 [ # # ]: 0 : if (i == idx+1) offset_next = offset;
182 : 0 : offset += sizeof(key_len_t) + keylen + vsize;
183 : : }
184 : : // remove
185 : 0 : memmove((uint8_t*)ptr + offset_idx, (uint8_t*)ptr + offset_next,
186 : 0 : next_len);
187 : : }
188 : 1 : }
189 : :
190 : 1 : static void _copy_str_kv(struct bnode *node_dst,
191 : : struct bnode *node_src,
192 : : idx_t dst_idx,
193 : : idx_t src_idx,
194 : : idx_t len)
195 : : {
196 : : int i;
197 : : int ksize, vsize;
198 : : void *ptr_src, *ptr_dst;
199 : : key_len_t keylen, _keylen;
200 : : size_t src_offset, src_len, dst_offset;
201 : :
202 [ - + ]: 2 : if (node_dst == node_src) return;
203 : :
204 : 1 : _get_kvsize(node_src->kvsize, ksize, vsize);
205 : :
206 : 1 : ptr_src = node_src->data;
207 : 1 : ptr_dst = node_dst->data;
208 : :
209 : : // calculate offset of 0 ~ src_idx-1
210 : 1 : src_offset = 0;
211 [ - + ]: 1 : for (i=0;i<src_idx;++i){
212 : 0 : memcpy(&_keylen, (uint8_t*)ptr_src + src_offset, sizeof(key_len_t));
213 : 0 : keylen = _endian_decode(_keylen);
214 : 0 : src_offset += sizeof(key_len_t) + keylen + vsize;
215 : : }
216 : :
217 : : // calculate offset of 0 ~ dst_idx-1
218 : 1 : dst_offset = 0;
219 [ - + ]: 1 : for (i=0;i<dst_idx;++i){
220 : 0 : memcpy(&_keylen, (uint8_t*)ptr_dst + dst_offset, sizeof(key_len_t));
221 : 0 : keylen = _endian_decode(_keylen);
222 : 0 : dst_offset += sizeof(key_len_t) + keylen + vsize;
223 : : }
224 : :
225 : : // calculate data length to be copied
226 : 1 : src_len = 0;
227 [ + + ]: 2 : for (i=src_idx ; i<src_idx+len ; ++i){
228 : 1 : memcpy(&_keylen, (uint8_t*)ptr_src + src_offset + src_len, sizeof(key_len_t));
229 : 1 : keylen = _endian_decode(_keylen);
230 : 1 : src_len += sizeof(key_len_t) + keylen + vsize;
231 : : }
232 : :
233 : : // copy
234 : 1 : memcpy((uint8_t*)ptr_dst + dst_offset, (uint8_t*)ptr_src + src_offset, src_len);
235 : : }
236 : :
237 : 4 : static size_t _get_str_kv_size(struct btree *tree, void *key, void *value)
238 : : {
239 : : void *key_ptr;
240 : : key_len_t keylen, _keylen;
241 : :
242 [ + + ]: 4 : if (key) {
243 : 2 : memcpy(&key_ptr, key, sizeof(void *));
244 : 2 : memcpy(&_keylen, key_ptr, sizeof(key_len_t));
245 : 2 : keylen = _endian_decode(_keylen);
246 : : }
247 : :
248 [ + + ][ + + ]: 4 : return ((key)?(sizeof(key_len_t) + keylen):0) + ((value)?tree->vsize:0);
249 : : }
250 : :
251 : 3 : static size_t _get_str_data_size(
252 : : struct bnode *node, void *new_minkey, void *key_arr, void *value_arr, size_t len)
253 : : {
254 : : int ksize, vsize, i;
255 : : void *ptr, *key_ptr;
256 : : size_t offset, size;
257 : : key_len_t keylen, _keylen;
258 : :
259 : 3 : _get_kvsize(node->kvsize, ksize, vsize);
260 : 3 : ksize = sizeof(void *);
261 : :
262 : 3 : ptr = node->data;
263 : 3 : offset = size = 0;
264 : :
265 [ + + ]: 7 : for (i=0;i<node->nentry;++i){
266 : 4 : memcpy(&_keylen, (uint8_t*)ptr + offset, sizeof(key_len_t));
267 : 4 : keylen = _endian_decode(_keylen);
268 : 4 : offset += sizeof(key_len_t) + keylen + vsize;
269 : :
270 [ + + ][ + + ]: 4 : if (new_minkey && i==0) {
271 : : // if the minimum key should be replaced to NEW_MINKEY
272 : 1 : memcpy(&key_ptr, new_minkey, ksize);
273 : 1 : memcpy(&_keylen, key_ptr, sizeof(key_len_t));
274 : 1 : keylen = _endian_decode(_keylen);
275 : : }
276 : 4 : size += sizeof(key_len_t) + keylen + vsize;
277 : : }
278 : :
279 [ + - ][ + - ]: 3 : if (key_arr && value_arr && len > 0) {
[ + - ]
280 [ + + ]: 9 : for (i=0;i<len;++i){
281 : 6 : memcpy(&key_ptr, (uint8_t*)key_arr + ksize*i, ksize);
282 : 6 : memcpy(&_keylen, key_ptr, sizeof(key_len_t));
283 : 6 : keylen = _endian_decode(_keylen);
284 : 6 : size += sizeof(key_len_t) + keylen + vsize;
285 : : }
286 : : }
287 : :
288 : 3 : return size;
289 : : }
290 : :
291 : 2 : INLINE void _init_str_kv_var(struct btree *tree, void *key, void *value)
292 : : {
293 [ + + ]: 2 : if (key) memset(key, 0, sizeof(void *));
294 [ + + ]: 2 : if (value) memset(value, 0, tree->vsize);
295 : 2 : }
296 : :
297 : 2 : static void _free_str_kv_var(struct btree *tree, void *key, void *value)
298 : : {
299 : : void *key_ptr;
300 : :
301 : 2 : memcpy(&key_ptr, key, sizeof(void *));
302 [ + + ]: 2 : if (key_ptr) {
303 : 1 : free(key_ptr);
304 : 1 : key_ptr = NULL;
305 : 1 : memcpy(key, &key_ptr, sizeof(void *));
306 : : }
307 : 2 : }
308 : :
309 : 2 : static void _set_str_key(struct btree *tree, void *dst, void *src)
310 : : {
311 : : void *key_ptr_old, *key_ptr_new;
312 : : key_len_t keylen_new, _keylen_new, inflen, keylen_alloc;
313 : 2 : size_t size_key = sizeof(key_len_t);
314 : :
315 : 2 : memset(&inflen, 0xff, sizeof(inflen));
316 : :
317 : 2 : memcpy(&key_ptr_new, src, sizeof(void *));
318 : 2 : memcpy(&_keylen_new, key_ptr_new, size_key);
319 : 2 : keylen_new = _endian_decode(_keylen_new);
320 : :
321 : : // free previous key (if exist)
322 : 2 : memcpy(&key_ptr_old, dst, sizeof(void *));
323 [ + + ]: 2 : if (key_ptr_old) {
324 : 1 : free(key_ptr_old);
325 : : }
326 : :
327 [ + - ]: 2 : keylen_alloc = (keylen_new == inflen)?(0):(keylen_new);
328 : 2 : key_ptr_old = (void*)malloc(size_key + keylen_alloc);
329 : : // copy keylen
330 : 2 : memcpy(key_ptr_old, key_ptr_new, size_key);
331 [ + - ]: 2 : if (keylen_alloc) {
332 : 2 : memcpy((uint8_t*)key_ptr_old + size_key,
333 : 2 : (uint8_t*)key_ptr_new + size_key, keylen_new);
334 : : }
335 : 2 : memcpy(dst, &key_ptr_old, sizeof(void *));
336 : 2 : }
337 : :
338 : 2 : INLINE void _set_str_value(struct btree *tree, void *dst, void *src)
339 : : {
340 : 2 : memcpy(dst, src, tree->vsize);
341 : 2 : }
342 : :
343 : 3 : INLINE void _get_str_nth_idx(struct bnode *node, idx_t num,
344 : : idx_t den, idx_t *idx)
345 : : {
346 : 3 : size_t rem = node->nentry - (int)(node->nentry / den) * den;
347 : 3 : *idx = (int)(node->nentry / den) * num + ((num < rem)?(num):(rem));
348 : 3 : }
349 : :
350 : 0 : INLINE void _get_str_nth_splitter(struct bnode *prev_node,
351 : : struct bnode *node, void *key)
352 : : {
353 : : // always return the smallest key of 'node'
354 : 0 : _get_str_kv(node, 0, key, NULL);
355 : 0 : }
356 : :
357 : 1 : void btree_str_kv_set_key(void *key, void *str, size_t len)
358 : : {
359 : : void *key_ptr;
360 : 1 : key_len_t keylen = len;
361 : : key_len_t _keylen;
362 : :
363 : 1 : key_ptr = (void *)malloc(sizeof(key_len_t) + keylen);
364 : 1 : _keylen = _endian_encode(keylen);
365 : 1 : memcpy(key_ptr, &_keylen, sizeof(key_len_t));
366 : 1 : memcpy((uint8_t*)key_ptr + sizeof(key_len_t), str, keylen);
367 : 1 : memcpy(key, &key_ptr, sizeof(void *));
368 : 1 : }
369 : :
370 : : // create an infinite key that is larger than any other keys
371 : 0 : void btree_str_kv_set_inf_key(void *key)
372 : : {
373 : : void *key_ptr;
374 : : key_len_t keylen;
375 : : key_len_t _keylen;
376 : :
377 : : // just containing length (0xff..) info
378 : 0 : key_ptr = (void *)malloc(sizeof(key_len_t));
379 : 0 : memset(&keylen, 0xff, sizeof(key_len_t));
380 : 0 : _keylen = _endian_encode(keylen);
381 : 0 : memcpy(key_ptr, &_keylen, sizeof(key_len_t));
382 : 0 : memcpy(key, &key_ptr, sizeof(void *));
383 : 0 : }
384 : :
385 : : // return true if KEY is infinite key
386 : 0 : int btree_str_kv_is_inf_key(void *key)
387 : : {
388 : : void *key_ptr;
389 : : key_len_t keylen, inflen;
390 : : key_len_t _keylen;
391 : :
392 : 0 : memset(&inflen, 0xff, sizeof(key_len_t));
393 : 0 : memcpy(&key_ptr, key, sizeof(void *));
394 [ # # ]: 0 : if (key_ptr) {
395 : 0 : memcpy(&_keylen, key_ptr, sizeof(key_len_t));
396 : 0 : keylen = _endian_decode(_keylen);
397 [ # # ]: 0 : if (keylen == inflen) {
398 : 0 : return 1;
399 : : }
400 : : }
401 : 0 : return 0;
402 : : }
403 : :
404 : 2 : void btree_str_kv_get_key(void *key, void *strbuf, size_t *len)
405 : : {
406 : : void *key_ptr;
407 : : key_len_t keylen, inflen;
408 : : key_len_t _keylen;
409 : :
410 : 2 : memset(&inflen, 0xff, sizeof(key_len_t));
411 : :
412 : 2 : memcpy(&key_ptr, key, sizeof(void *));
413 [ + + ]: 2 : if (key_ptr) {
414 : 1 : memcpy(&_keylen, key_ptr, sizeof(key_len_t));
415 : 1 : keylen = _endian_decode(_keylen);
416 : :
417 : 1 : memcpy(strbuf, (uint8_t*)key_ptr + sizeof(key_len_t), keylen);
418 : 1 : *len = keylen;
419 : : } else {
420 : 1 : *len = 0;
421 : : }
422 : 2 : }
423 : :
424 : 1 : void btree_str_kv_free_key(void *key)
425 : : {
426 : : void *key_ptr;
427 : 1 : memcpy(&key_ptr, key, sizeof(void *));
428 [ + - ]: 1 : if (key_ptr) free(key_ptr);
429 : 1 : key_ptr = NULL;
430 : 1 : memcpy(key, &key_ptr, sizeof(void *));
431 : 1 : }
432 : :
433 : 1 : INLINE bid_t _str_value_to_bid_64(void *value)
434 : : {
435 : 1 : return *((bid_t *)value);
436 : : }
437 : :
438 : 1 : INLINE void* _str_bid_to_value_64(bid_t *bid)
439 : : {
440 : 1 : return (void *)bid;
441 : : }
442 : :
443 : 7 : int _cmp_str64(void *key1, void *key2, void* aux)
444 : : {
445 : : (void) aux;
446 : : void *key_ptr1, *key_ptr2;
447 : : key_len_t keylen1, keylen2, inflen;
448 : : key_len_t _keylen1, _keylen2;
449 : :
450 : 7 : memcpy(&key_ptr1, key1, sizeof(void *));
451 : 7 : memcpy(&key_ptr2, key2, sizeof(void *));
452 : :
453 [ + + ][ + + ]: 7 : if (key_ptr1 == NULL && key_ptr2 == NULL) {
454 : 1 : return 0;
455 [ + + ]: 6 : } else if (key_ptr1 == NULL) {
456 : 1 : return -1;
457 [ + + ]: 5 : } else if (key_ptr2 == NULL) {
458 : 1 : return 1;
459 : : }
460 : :
461 : 4 : memcpy(&_keylen1, key_ptr1, sizeof(key_len_t));
462 : 4 : memcpy(&_keylen2, key_ptr2, sizeof(key_len_t));
463 : 4 : keylen1 = _endian_decode(_keylen1);
464 : 4 : keylen2 = _endian_decode(_keylen2);
465 : :
466 : 4 : memset(&inflen, 0xff, sizeof(key_len_t));
467 [ - + ]: 4 : if (keylen1 == inflen) {
468 : 0 : return 1;
469 [ - + ]: 4 : } else if (keylen2 == inflen) {
470 : 0 : return -1;
471 : : }
472 : :
473 [ + + ]: 4 : if (keylen1 == keylen2) {
474 : : return memcmp((uint8_t*)key_ptr1 + sizeof(key_len_t),
475 : 2 : (uint8_t*)key_ptr2 + sizeof(key_len_t), keylen1);
476 : : }else{
477 [ + - ]: 2 : key_len_t len = MIN(keylen1, keylen2);
478 : : int cmp = memcmp((uint8_t*)key_ptr1 + sizeof(key_len_t),
479 : 2 : (uint8_t*)key_ptr2 + sizeof(key_len_t), len);
480 [ + + ]: 2 : if (cmp != 0) return cmp;
481 : : else {
482 : 7 : return (int)((int)keylen1 - (int)keylen2);
483 : : }
484 : : }
485 : : }
486 : :
487 : 15 : struct btree_kv_ops * btree_str_kv_get_kb64_vb64(struct btree_kv_ops *kv_ops)
488 : : {
489 : : struct btree_kv_ops *btree_kv_ops;
490 [ + + ]: 15 : if (kv_ops) {
491 : 9 : btree_kv_ops = kv_ops;
492 : : }else{
493 : 6 : btree_kv_ops = (struct btree_kv_ops *)malloc(sizeof(struct btree_kv_ops));
494 : : }
495 : :
496 : 15 : btree_kv_ops->get_kv = _get_str_kv;
497 : 15 : btree_kv_ops->set_kv = _set_str_kv;
498 : 15 : btree_kv_ops->ins_kv = _ins_str_kv;
499 : 15 : btree_kv_ops->copy_kv = _copy_str_kv;
500 : 15 : btree_kv_ops->set_key = _set_str_key;
501 : 15 : btree_kv_ops->set_value = _set_str_value;
502 : 15 : btree_kv_ops->get_data_size = _get_str_data_size;
503 : 15 : btree_kv_ops->get_kv_size = _get_str_kv_size;
504 : 15 : btree_kv_ops->init_kv_var = _init_str_kv_var;
505 : 15 : btree_kv_ops->free_kv_var = _free_str_kv_var;
506 : :
507 : 15 : btree_kv_ops->get_nth_idx = _get_str_nth_idx;
508 : 15 : btree_kv_ops->get_nth_splitter = _get_str_nth_splitter;
509 : :
510 : 15 : btree_kv_ops->cmp = _cmp_str64;
511 : :
512 : 15 : btree_kv_ops->bid2value = _str_bid_to_value_64;
513 : 15 : btree_kv_ops->value2bid = _str_value_to_bid_64;
514 : :
515 : 15 : return btree_kv_ops;
516 : : }
|