1/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3/*======
4This file is part of PerconaFT.
5
6
7Copyright (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#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
37
38#pragma once
39
40#include <db.h>
41#include <string.h>
42
43#include "portability/memory.h"
44
45#include "util/dbt.h"
46
47typedef int (*ft_compare_func)(DB *db, const DBT *a, const DBT *b);
48
49int toku_keycompare(const void *key1, uint32_t key1len, const void *key2, uint32_t key2len);
50
51int toku_builtin_compare_fun (DB *, const DBT *, const DBT*) __attribute__((__visibility__("default")));
52
53namespace toku {
54
55 // a comparator object encapsulates the data necessary for
56 // comparing two keys in a fractal tree. it further understands
57 // that points may be positive or negative infinity.
58
59 class comparator {
60 void init(ft_compare_func cmp, DESCRIPTOR desc, uint8_t memcmp_magic) {
61 _cmp = cmp;
62 _fake_db->cmp_descriptor = desc;
63 _memcmp_magic = memcmp_magic;
64 }
65
66 public:
67 // This magic value is reserved to mean that the magic has not been set.
68 static const uint8_t MEMCMP_MAGIC_NONE = 0;
69
70 void create(ft_compare_func cmp, DESCRIPTOR desc, uint8_t memcmp_magic = MEMCMP_MAGIC_NONE) {
71 XCALLOC(_fake_db);
72 init(cmp, desc, memcmp_magic);
73 }
74
75 // inherit the attributes of another comparator, but keep our own
76 // copy of fake_db that is owned separately from the one given.
77 void inherit(const comparator &cmp) {
78 invariant_notnull(_fake_db);
79 invariant_notnull(cmp._cmp);
80 invariant_notnull(cmp._fake_db);
81 init(cmp._cmp, cmp._fake_db->cmp_descriptor, cmp._memcmp_magic);
82 }
83
84 // like inherit, but doesn't require that the this comparator
85 // was already created
86 void create_from(const comparator &cmp) {
87 XCALLOC(_fake_db);
88 inherit(cmp);
89 }
90
91 void destroy() {
92 toku_free(_fake_db);
93 }
94
95 const DESCRIPTOR_S *get_descriptor() const {
96 return _fake_db->cmp_descriptor;
97 }
98
99 ft_compare_func get_compare_func() const {
100 return _cmp;
101 }
102
103 uint8_t get_memcmp_magic() const {
104 return _memcmp_magic;
105 }
106
107 bool valid() const {
108 return _cmp != nullptr;
109 }
110
111 inline bool dbt_has_memcmp_magic(const DBT *dbt) const {
112 return *reinterpret_cast<const char *>(dbt->data) == _memcmp_magic;
113 }
114
115 int operator()(const DBT *a, const DBT *b) const {
116 if (__builtin_expect(toku_dbt_is_infinite(a) || toku_dbt_is_infinite(b), 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 return toku_builtin_compare_fun(nullptr, a, b);
124 } else {
125 // yikes, const sadness here
126 return _cmp(const_cast<DB *>(_fake_db), a, b);
127 }
128 }
129
130 private:
131 DB *_fake_db;
132 ft_compare_func _cmp;
133 uint8_t _memcmp_magic;
134 };
135
136} /* namespace toku */
137