1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: 3 /*====== 4 This file is part of PerconaFT. 5 6 7 Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. 8 9 PerconaFT is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License, version 2, 11 as published by the Free Software Foundation. 12 13 PerconaFT is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. 20 21 ---------------------------------------- 22 23 PerconaFT is free software: you can redistribute it and/or modify 24 it under the terms of the GNU Affero General Public License, version 3, 25 as published by the Free Software Foundation. 26 27 PerconaFT is distributed in the hope that it will be useful, 28 but WITHOUT ANY WARRANTY; without even the implied warranty of 29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 GNU Affero General Public License for more details. 31 32 You should have received a copy of the GNU Affero General Public License 33 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. 34 35 ---------------------------------------- 36 37 Licensed under the Apache License, Version 2.0 (the "License"); 38 you may not use this file except in compliance with the License. 39 You may obtain a copy of the License at 40 41 http://www.apache.org/licenses/LICENSE-2.0 42 43 Unless required by applicable law or agreed to in writing, software 44 distributed under the License is distributed on an "AS IS" BASIS, 45 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 46 See the License for the specific language governing permissions and 47 limitations under the License. 48 ======= */ 49 50 #ident \ 51 "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." 52 53 #pragma once 54 55 #include <string.h> 56 57 #include "../db.h" 58 #include "../portability/memory.h" 59 #include "../util/dbt.h" 60 61 typedef int (*ft_compare_func)(void *arg, const DBT *a, const DBT *b); 62 63 int toku_keycompare(const void *key1, size_t key1len, const void *key2, 64 size_t key2len); 65 66 int toku_builtin_compare_fun(const DBT *, const DBT *) 67 __attribute__((__visibility__("default"))); 68 69 namespace toku { 70 71 // a comparator object encapsulates the data necessary for 72 // comparing two keys in a fractal tree. it further understands 73 // that points may be positive or negative infinity. 74 75 class comparator { init(ft_compare_func cmp,void * cmp_arg,uint8_t memcmp_magic)76 void init(ft_compare_func cmp, void *cmp_arg, uint8_t memcmp_magic) { 77 _cmp = cmp; 78 _cmp_arg = cmp_arg; 79 _memcmp_magic = memcmp_magic; 80 } 81 82 public: 83 // This magic value is reserved to mean that the magic has not been set. 84 static const uint8_t MEMCMP_MAGIC_NONE = 0; 85 86 void create(ft_compare_func cmp, void *cmp_arg, 87 uint8_t memcmp_magic = MEMCMP_MAGIC_NONE) { 88 init(cmp, cmp_arg, memcmp_magic); 89 } 90 91 // inherit the attributes of another comparator, but keep our own 92 // copy of fake_db that is owned separately from the one given. inherit(const comparator & cmp)93 void inherit(const comparator &cmp) { 94 invariant_notnull(cmp._cmp); 95 init(cmp._cmp, cmp._cmp_arg, cmp._memcmp_magic); 96 } 97 98 // like inherit, but doesn't require that the this comparator 99 // was already created create_from(const comparator & cmp)100 void create_from(const comparator &cmp) { inherit(cmp); } 101 destroy()102 void destroy() {} 103 get_compare_func()104 ft_compare_func get_compare_func() const { return _cmp; } 105 get_memcmp_magic()106 uint8_t get_memcmp_magic() const { return _memcmp_magic; } 107 valid()108 bool valid() const { return _cmp != nullptr; } 109 dbt_has_memcmp_magic(const DBT * dbt)110 inline bool dbt_has_memcmp_magic(const DBT *dbt) const { 111 return *reinterpret_cast<const char *>(dbt->data) == _memcmp_magic; 112 } 113 operator()114 int operator()(const DBT *a, const DBT *b) const { 115 if (__builtin_expect(toku_dbt_is_infinite(a) || toku_dbt_is_infinite(b), 116 0)) { 117 return toku_dbt_infinite_compare(a, b); 118 } else if (_memcmp_magic != MEMCMP_MAGIC_NONE 119 // If `a' has the memcmp magic.. 120 && dbt_has_memcmp_magic(a) 121 // ..then we expect `b' to also have the memcmp magic 122 && __builtin_expect(dbt_has_memcmp_magic(b), 1)) { 123 assert(0); // psergey: this branch should not be taken. 124 return toku_builtin_compare_fun(a, b); 125 } else { 126 // yikes, const sadness here 127 return _cmp(_cmp_arg, a, b); 128 } 129 } 130 131 private: 132 ft_compare_func _cmp; 133 void *_cmp_arg; 134 135 uint8_t _memcmp_magic; 136 }; 137 138 } /* namespace toku */ 139