1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3 #ident "$Id$"
4 /*======
5 This file is part of PerconaFT.
6 
7 
8 Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved.
9 
10     PerconaFT is free software: you can redistribute it and/or modify
11     it under the terms of the GNU General Public License, version 2,
12     as published by the Free Software Foundation.
13 
14     PerconaFT is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18 
19     You should have received a copy of the GNU General Public License
20     along with PerconaFT.  If not, see <http://www.gnu.org/licenses/>.
21 
22 ----------------------------------------
23 
24     PerconaFT is free software: you can redistribute it and/or modify
25     it under the terms of the GNU Affero General Public License, version 3,
26     as published by the Free Software Foundation.
27 
28     PerconaFT is distributed in the hope that it will be useful,
29     but WITHOUT ANY WARRANTY; without even the implied warranty of
30     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31     GNU Affero General Public License for more details.
32 
33     You should have received a copy of the GNU Affero General Public License
34     along with PerconaFT.  If not, see <http://www.gnu.org/licenses/>.
35 ======= */
36 
37 #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved."
38 
39 #include <db.h>
40 #include <string.h>
41 
42 #include "portability/memory.h"
43 
44 #include "util/dbt.h"
45 
toku_init_dbt(DBT * dbt)46 DBT *toku_init_dbt(DBT *dbt) {
47     memset(dbt, 0, sizeof(*dbt));
48     return dbt;
49 }
50 
toku_empty_dbt(void)51 DBT toku_empty_dbt(void) {
52     static const DBT empty_dbt = { .data = 0, .size = 0, .ulen = 0, .flags = 0 };
53     return empty_dbt;
54 }
55 
toku_init_dbt_flags(DBT * dbt,uint32_t flags)56 DBT *toku_init_dbt_flags(DBT *dbt, uint32_t flags) {
57     toku_init_dbt(dbt);
58     dbt->flags = flags;
59     return dbt;
60 }
61 
toku_dbt_array_init(DBT_ARRAY * dbts,uint32_t size)62 DBT_ARRAY *toku_dbt_array_init(DBT_ARRAY *dbts, uint32_t size) {
63     uint32_t capacity = 1;
64     while (capacity < size) { capacity *= 2; }
65 
66     XMALLOC_N(capacity, dbts->dbts);
67     for (uint32_t i = 0; i < capacity; i++) {
68         toku_init_dbt_flags(&dbts->dbts[i], DB_DBT_REALLOC);
69     }
70     dbts->size = size;
71     dbts->capacity = capacity;
72     return dbts;
73 }
74 
toku_dbt_array_resize(DBT_ARRAY * dbts,uint32_t size)75 void toku_dbt_array_resize(DBT_ARRAY *dbts, uint32_t size) {
76     if (size != dbts->size) {
77         if (size > dbts->capacity) {
78             const uint32_t old_capacity = dbts->capacity;
79             uint32_t new_capacity = dbts->capacity;
80             while (new_capacity < size) {
81                 new_capacity *= 2;
82             }
83             dbts->capacity = new_capacity;
84             XREALLOC_N(new_capacity, dbts->dbts);
85             for (uint32_t i = old_capacity; i < new_capacity; i++) {
86                 toku_init_dbt_flags(&dbts->dbts[i], DB_DBT_REALLOC);
87             }
88         } else if (size < dbts->size) {
89             if (dbts->capacity >= 8 && size < dbts->capacity / 4) {
90                 const int old_capacity = dbts->capacity;
91                 const int new_capacity = dbts->capacity / 2;
92                 for (int i = new_capacity; i < old_capacity; i++) {
93                     toku_destroy_dbt(&dbts->dbts[i]);
94                 }
95                 XREALLOC_N(new_capacity, dbts->dbts);
96                 dbts->capacity = new_capacity;
97             }
98         }
99         dbts->size = size;
100     }
101 }
102 
toku_dbt_array_destroy_shallow(DBT_ARRAY * dbts)103 void toku_dbt_array_destroy_shallow(DBT_ARRAY *dbts) {
104     toku_free(dbts->dbts);
105     ZERO_STRUCT(*dbts);
106 }
107 
toku_dbt_array_destroy(DBT_ARRAY * dbts)108 void toku_dbt_array_destroy(DBT_ARRAY *dbts) {
109     for (uint32_t i = 0; i < dbts->capacity; i++) {
110         toku_destroy_dbt(&dbts->dbts[i]);
111     }
112     toku_dbt_array_destroy_shallow(dbts);
113 }
114 
115 
116 
toku_destroy_dbt(DBT * dbt)117 void toku_destroy_dbt(DBT *dbt) {
118     switch (dbt->flags) {
119     case DB_DBT_MALLOC:
120     case DB_DBT_REALLOC:
121         toku_free(dbt->data);
122         toku_init_dbt(dbt);
123         break;
124     }
125 }
126 
toku_fill_dbt(DBT * dbt,const void * k,uint32_t len)127 DBT *toku_fill_dbt(DBT *dbt, const void *k, uint32_t len) {
128     toku_init_dbt(dbt);
129     dbt->size=len;
130     dbt->data=(char*)k;
131     return dbt;
132 }
133 
toku_memdup_dbt(DBT * dbt,const void * k,size_t len)134 DBT *toku_memdup_dbt(DBT *dbt, const void *k, size_t len) {
135     toku_init_dbt_flags(dbt, DB_DBT_MALLOC);
136     dbt->size = len;
137     dbt->data = toku_xmemdup(k, len);
138     return dbt;
139 }
140 
toku_copyref_dbt(DBT * dst,const DBT src)141 DBT *toku_copyref_dbt(DBT *dst, const DBT src) {
142     dst->flags = 0;
143     dst->ulen = 0;
144     dst->size = src.size;
145     dst->data = src.data;
146     return dst;
147 }
148 
toku_clone_dbt(DBT * dst,const DBT & src)149 DBT *toku_clone_dbt(DBT *dst, const DBT &src) {
150     return toku_memdup_dbt(dst, src.data, src.size);
151 }
152 
153 void
toku_sdbt_cleanup(struct simple_dbt * sdbt)154 toku_sdbt_cleanup(struct simple_dbt *sdbt) {
155     if (sdbt->data) toku_free(sdbt->data);
156     memset(sdbt, 0, sizeof(*sdbt));
157 }
158 
sdbt_realloc(struct simple_dbt * sdbt)159 static inline int sdbt_realloc(struct simple_dbt *sdbt) {
160     void *new_data = toku_realloc(sdbt->data, sdbt->len);
161     int r;
162     if (new_data == NULL) {
163         r = get_error_errno();
164     } else {
165         sdbt->data = new_data;
166         r = 0;
167     }
168     return r;
169 }
170 
dbt_realloc(DBT * dbt)171 static inline int dbt_realloc(DBT *dbt) {
172     void *new_data = toku_realloc(dbt->data, dbt->ulen);
173     int r;
174     if (new_data == NULL) {
175         r = get_error_errno();
176     } else {
177         dbt->data = new_data;
178         r = 0;
179     }
180     return r;
181 }
182 
183 // sdbt is the static value used when flags==0
184 // Otherwise malloc or use the user-supplied memory, as according to the flags in d->flags.
toku_dbt_set(uint32_t len,const void * val,DBT * d,struct simple_dbt * sdbt)185 int toku_dbt_set(uint32_t len, const void *val, DBT *d, struct simple_dbt *sdbt) {
186     int r;
187     if (d == nullptr) {
188         r = 0;
189     } else {
190         switch (d->flags) {
191         case (DB_DBT_USERMEM):
192             d->size = len;
193             if (d->ulen<len) r = DB_BUFFER_SMALL;
194             else {
195                 memcpy(d->data, val, len);
196                 r = 0;
197             }
198             break;
199         case (DB_DBT_MALLOC):
200             d->data = NULL;
201             d->ulen = 0;
202             // fallthrough
203             // to DB_DBT_REALLOC
204         case (DB_DBT_REALLOC):
205             if (d->ulen < len) {
206                 d->ulen = len*2;
207                 r = dbt_realloc(d);
208             }
209             else if (d->ulen > 16 && d->ulen > len*4) {
210                 d->ulen = len*2 < 16 ? 16 : len*2;
211                 r = dbt_realloc(d);
212             }
213             else if (d->data==NULL) {
214                 d->ulen = len;
215                 r = dbt_realloc(d);
216             }
217             else r=0;
218 
219             if (r==0) {
220                 memcpy(d->data, val, len);
221                 d->size = len;
222             }
223             break;
224         case (0):
225             if (sdbt->len < len) {
226                 sdbt->len = len*2;
227                 r = sdbt_realloc(sdbt);
228             }
229             else if (sdbt->len > 16 && sdbt->len > len*4) {
230                 sdbt->len = len*2 < 16 ? 16 : len*2;
231                 r = sdbt_realloc(sdbt);
232             }
233             else r=0;
234 
235             if (r==0) {
236                 memcpy(sdbt->data, val, len);
237                 d->data = sdbt->data;
238                 d->size = len;
239             }
240             break;
241         default:
242             r = EINVAL;
243             break;
244         }
245     }
246     return r;
247 }
248 
toku_dbt_positive_infinity(void)249 const DBT *toku_dbt_positive_infinity(void) {
250     static DBT positive_infinity_dbt = {};
251     return &positive_infinity_dbt;
252 }
253 
toku_dbt_negative_infinity(void)254 const DBT *toku_dbt_negative_infinity(void) {
255     static DBT negative_infinity_dbt = {};
256     return &negative_infinity_dbt;
257 }
258 
toku_dbt_is_infinite(const DBT * dbt)259 bool toku_dbt_is_infinite(const DBT *dbt) {
260     return dbt == toku_dbt_positive_infinity() || dbt == toku_dbt_negative_infinity();
261 }
262 
toku_dbt_is_empty(const DBT * dbt)263 bool toku_dbt_is_empty(const DBT *dbt) {
264     // can't have a null data field with a non-zero size
265     paranoid_invariant(dbt->data != nullptr || dbt->size == 0);
266     return dbt->data == nullptr;
267 }
268 
toku_dbt_infinite_compare(const DBT * a,const DBT * b)269 int toku_dbt_infinite_compare(const DBT *a, const DBT *b) {
270     if (a == b) {
271         return 0;
272     } else if (a == toku_dbt_positive_infinity()) {
273         return 1;
274     } else if (b == toku_dbt_positive_infinity()) {
275         return -1;
276     } else if (a == toku_dbt_negative_infinity()) {
277         return -1;
278     } else {
279         invariant(b == toku_dbt_negative_infinity());
280         return 1;
281     }
282 }
283 
toku_dbt_equals(const DBT * a,const DBT * b)284 bool toku_dbt_equals(const DBT *a, const DBT *b) {
285     if (!toku_dbt_is_infinite(a) && !toku_dbt_is_infinite(b)) {
286         return a->data == b->data && a->size == b->size;
287     } else {
288         // a or b is infinite, so they're equal if they are the same infinite
289         return a == b ? true : false;
290     }
291 }
292