taco-db  0.1.0
tdb_base.h
Go to the documentation of this file.
1 #ifndef TDB_BASE_H
2 #define TDB_BASE_H
3 
12 #include "config.h"
13 
14 // Always prefer the C++ new/delete expressions rather than using malloc except
15 // when one needs aligned_alloc(3) because aligned new is not available until
16 // C++17.
17 #ifdef USE_JEMALLOC
18 # include <jemalloc/jemalloc.h>
19 #else
20 # include <cstdlib>
21 
22 using std::free;
23 
24 // aligned_alloc is not in C++11 but should be available as long as
25 // _ISOC11_SOURCE is defined
26 #ifndef _ISOC11_SOURCE
27 #if __cplusplus >= 201703L
28 using std::aligned_alloc;
29 #else // __cplusplus < 201703L
30 #error "need a working aligned_alloc(3)"
31 #endif // __cplusplus
32 #endif // _ISOC11_SOURCE
33 
34 #endif // USE_JEMALLOC
35 
36 #include <memory>
37 #include <iostream>
38 #include <fstream>
39 #include <cstdlib>
40 #include <cstring>
41 #include <cstddef>
42 #include <cstdint>
43 #include <cstdio>
44 #include <cctype>
45 #include <new>
46 #include <string>
47 #include <vector>
48 #include <utility>
49 #include <functional>
50 #include <limits>
51 
52 #include "base/atomics.h"
53 
54 #include <absl/base/macros.h>
55 #include <absl/memory/memory.h>
56 #include <absl/strings/string_view.h>
57 
58 using std::size_t;
59 using std::ptrdiff_t;
60 using std::uint64_t;
61 using std::int64_t;
62 using std::uint32_t;
63 using std::int32_t;
64 using std::uint16_t;
65 using std::int16_t;
66 using std::int8_t;
67 using std::uint8_t;
68 using std::uintptr_t;
69 using std::intptr_t;
70 
71 using std::static_pointer_cast;
72 using std::dynamic_pointer_cast;
73 using std::const_pointer_cast;
74 #if __cplusplus >= 201703L
75 // this is available starting from C++17
77 #else
78 template<class T, class U>
79 static inline std::shared_ptr<T>
80 reinterpret_pointer_cast(const std::shared_ptr<U>& p) {
81  return std::shared_ptr<T>(p, reinterpret_cast<T*>(p.get()));
82 }
83 #endif
84 
85 namespace AlignedAllocImpl {
86 struct FreeMem {
87  void operator()(void *x) {
88  free(x);
89  }
90 };
91 } // AlignedAllocImpl
92 
93 typedef std::unique_ptr<void, AlignedAllocImpl::FreeMem>
95 
100 inline unique_malloced_ptr
101 unique_aligned_alloc(size_t alignment, size_t size) {
102  return unique_malloced_ptr(aligned_alloc(alignment, size));
103 }
104 
105 inline unique_malloced_ptr
106 wrap_malloc(void *ptr) {
107  return unique_malloced_ptr(ptr);
108 }
109 
110 inline unique_malloced_ptr
111 unique_malloc(size_t size) {
112  return unique_malloced_ptr(malloc(size));
113 }
114 
115 namespace AlignedAllocImpl {
116 
117 template<size_t alignment, class T>
119  typedef T value_type;
120  typedef size_t size_type;
121  typedef ptrdiff_t difference_type;
122 
123  static T*
124  allocate(size_t n) {
125  return (T*) aligned_alloc(alignment, n * sizeof(T));
126  }
127 
128  static void
129  deallocate(T *p, size_t) {
130  free(p);
131  }
132 
133  constexpr bool
135  return true;
136  }
137 
138  constexpr bool
140  return false;
141  }
142 
143  typedef std::true_type is_always_equal;
144 
145  template<class U>
146  struct rebind {
148  };
149 };
150 
151 
152 } // AlignedAllocImpl
153 
154 using maxaligned_char_buf =
155  std::vector<char, AlignedAllocImpl::aligned_allocator<8, char>>;
156 
157 
158 constexpr const size_t CACHELINE_SIZE = L1_CACHELINE_SIZE;
159 constexpr const size_t PAGE_SIZE = CONFIG_PAGE_SIZE;
160 
161 
162 #include "base/logging.h"
163 #include "utils/misc.h"
164 
165 // ASSERT(condition [, <fmtstring> [, <args>]...])
166 //
167 // Assertion is enabled when NDEBUG is not defined. Here we do not use the
168 // standard C assert() macro. Instead, it throws a fatal error so that our
169 // exception handler can catch it and provide better insight rather than an
170 // abort() call.
171 #if (defined(TDB_IN_TEST) && !defined(NDEBUG))
172 // In-test asserts shouldn't add the file location in the log, as they are
173 // always included in the log message.
174 #define ASSERT(...) \
175  do { \
176  bool __cond = (CAR(__VA_ARGS__)); \
177  if (!__cond) { \
178  LOG(::taco::kFatal, \
179  "assertion \"" \
180  STRINGIFY(CAR(__VA_ARGS__)) \
181  "\" failed" \
182  IF_NONEMPTY_COMMA(CADR(__VA_ARGS__), ": ") \
183  CDR(__VA_ARGS__) \
184  ); \
185  } \
186  } while (0)
187 #elif (!defined(TDB_IN_TEST) && !defined(NDEBUG))
188 // Non-test assert failure should be a fatal error and needs to log a file
189 // location for debugging
190 #define ASSERT(...) \
191  do { \
192  bool __cond = (CAR(__VA_ARGS__)); \
193  if (!__cond) { \
194  LOG(::taco::kFatal, "%s:" STRINGIFY(__LINE__) \
195  ": assertion \"" \
196  STRINGIFY(CAR(__VA_ARGS__)) \
197  "\" failed" \
198  IF_NONEMPTY(CADR(__VA_ARGS__), ": "), \
199  ::taco::StripSourcePath(__FILE__) \
200  IF_NONEMPTY_COMMA(CADR(__VA_ARGS__), ) \
201  CDR(__VA_ARGS__) \
202  ); \
203  } \
204  } while (0)
205 #else // assert disabled
206 #define ASSERT(...)
207 #endif
208 
209 namespace taco {
210 
211 typedef uint32_t Oid;
212 typedef int16_t FieldOffset;
213 typedef int16_t FieldId;
214 typedef uint32_t PageNumber;
215 typedef uint64_t BufferId;
216 
222 typedef uint32_t FileId;
223 typedef uint16_t SlotId;
224 
225 constexpr Oid InvalidOid = 0;
226 constexpr FieldId InvalidFieldId = 0x7fff;
227 constexpr FieldId MaxNumRegularFieldId = 0x7fff;
228 constexpr int PageNumberBits = 32;
230 static_assert(FieldOffsetBits <= 15, "page size cannot be larger than 2^15");
232 
236 constexpr PageNumber INVALID_PID = 0;
237 
244 
249  (RESERVED_PID == ((((uint64_t) 1) << PageNumberBits) - 1))
250  ? (RESERVED_PID - 2) : ((((uint64_t) 1) << PageNumberBits) - 1);
251 
255 constexpr SlotId INVALID_SID = 0;
256 
260 constexpr SlotId MinSlotId = 1;
261 
265 constexpr SlotId MaxSlotId = (~(SlotId) 0) - 1;
266 
267 constexpr BufferId INVALID_BUFID = ~(BufferId) 0;
268 
269 #define FIELDOFFSET_FORMAT "%hd"
270 #define FIELDID_FORMAT "%hd"
271 #define OID_FORMAT "%u"
272 #define FILEID_FORMAT "%u"
273 #define PAGENUMBER_FORMAT "0x%08X"
274 #define SLOTID_FORMAT "%hu"
275 #define BUFFERID_FORMAT "%lu"
276 
282 constexpr Oid MaxOid = std::numeric_limits<Oid>::max() - 1;
283 
285 typedef uint8_t IdxType;
286 
288 typedef uint8_t OpType;
289 
296 typedef uint8_t AggType;
297 
318 template<class T>
319 constexpr T
320 TYPEALIGN(uint64_t ALIGNVAL, T LEN) {
321  return (((uint64_t) (LEN) + ((ALIGNVAL) - 1)) & ~((uint64_t) ((ALIGNVAL) - 1)));
322 }
323 
324 #define SHORTALIGN(LEN) TYPEALIGN(2, (LEN))
325 #define INTALIGN(LEN) TYPEALIGN(4, (LEN))
326 #define LONGALIGN(LEN) TYPEALIGN(8, (LEN))
327 #define DOUBLEALIGN(LEN) TYPEALIGN(8, (LEN))
328 #define MAXALIGN(LEN) TYPEALIGN(8, (LEN))
329 #define CACHELINEALIGN(LEN) TYPEALIGN(CACHELINE_SIZE, (LEN))
330 #define MAXALIGN_OF 8
331 
332 template<class T>
333 constexpr T
334 TYPEALIGN_DOWN(uint64_t ALIGNVAL, T LEN) {
335  return (((uint64_t) (LEN)) & ~((uint64_t) ((ALIGNVAL) - 1)));
336 }
337 
338 #define SHORTALIGN_DOWN(LEN) TYPEALIGN_DOWN(2, (LEN))
339 #define INTALIGN_DOWN(LEN) TYPEALIGN_DOWN(4, (LEN))
340 #define LONGALIGN_DOWN(LEN) TYPEALIGN_DOWN(8, (LEN))
341 #define DOUBLEALIGN_DOWN(LEN) TYPEALIGN_DOWN(8, (LEN))
342 #define MAXALIGN_DOWN(LEN) TYPEALIGN_DOWN(8, (LEN))
343 #define BUFFERALIGN_DOWN(LEN) TYPEALIGN_DOWN(CACHELINE_SIZE, (LEN))
344 
345 template<class T, class U>
346 bool
347 AddWithCheck(T &left, U right) {
348  if ((left > 0 && (T) right > std::numeric_limits<T>::max() - left) ||
349  (left < 0 && (T) right < left - std::numeric_limits<T>::min())) {
350  return false;
351  }
352  left += (T) right;
353  return true;
354 }
355 
362 #define RETURN_IF(...) \
363  do { \
364  if ((CAR(__VA_ARGS__))) { \
365  return CDR(__VA_ARGS__); \
366  } \
367  } while(0)
368 
369 } // namespace taco
370 
376 #define FLEXIBLE_ARRAY_MEMBER -1
377 
378 #include "base/datum.h"
379 #include "base/fmgr.h"
380 
381 #ifdef ABSL_USES_STD_STRING_VIEW
382 #define cast_as_string(t) t
383 #else
384 
393 template<class T>
394 typename std::enable_if<!std::is_same<typename std::decay<T>::type,
395  absl::string_view>::value,
396  T&&>::type
398  return std::forward<T>(t);
399 }
400 
401 template<class T>
402 typename std::enable_if<std::is_same<typename std::decay<T>::type,
403  absl::string_view>::value,
404  std::string>::type
406  return std::string(t.data(), t.size());
407 }
408 
409 #endif // ABSL_USES_STD_STRING_VIEW
410 
411 #endif // TDB_BASE_H
taco::FieldOffset
int16_t FieldOffset
Definition: tdb_base.h:212
AlignedAllocImpl::aligned_allocator::is_always_equal
std::true_type is_always_equal
Definition: tdb_base.h:143
taco::INVALID_SID
constexpr SlotId INVALID_SID
The invalid slot ID.
Definition: tdb_base.h:255
taco::InvalidFieldId
constexpr FieldId InvalidFieldId
Definition: tdb_base.h:226
reinterpret_pointer_cast
static std::shared_ptr< T > reinterpret_pointer_cast(const std::shared_ptr< U > &p)
Definition: tdb_base.h:80
taco::OpType
uint8_t OpType
The operator type, see expr/optypes.h.
Definition: tdb_base.h:288
taco::IdxType
uint8_t IdxType
The index type, see index/idxtyps.h.
Definition: tdb_base.h:285
AlignedAllocImpl::aligned_allocator
Definition: tdb_base.h:118
taco::MaxNumRegularFieldId
constexpr FieldId MaxNumRegularFieldId
Definition: tdb_base.h:227
PAGE_SIZE
constexpr const size_t PAGE_SIZE
Definition: tdb_base.h:159
taco::INVALID_PID
constexpr PageNumber INVALID_PID
The invalid page number.
Definition: tdb_base.h:236
unique_aligned_alloc
unique_malloced_ptr unique_aligned_alloc(size_t alignment, size_t size)
Wraps an aligned_alloced'd memory space in a std::unique_ptr.
Definition: tdb_base.h:101
taco::MaxFieldOffset
constexpr FieldOffset MaxFieldOffset
Definition: tdb_base.h:231
taco::MinSlotId
constexpr SlotId MinSlotId
The minimum valid slot ID.
Definition: tdb_base.h:260
taco::logn_ceil
constexpr int logn_ceil(uint64_t x)
Returns $\lceil log_2(x) \rceil$ for x > 0, or 0 for x = 0.
Definition: misc.h:148
taco::RESERVED_PID
constexpr PageNumber RESERVED_PID
An invalid page number reserved for file manager internal use.
Definition: tdb_base.h:243
taco
Definition: datum.h:28
AlignedAllocImpl::FreeMem
Definition: tdb_base.h:86
datum.h
taco::SlotId
uint16_t SlotId
Definition: tdb_base.h:223
taco::BufferId
uint64_t BufferId
Definition: tdb_base.h:215
CONFIG_PAGE_SIZE
#define CONFIG_PAGE_SIZE
Definition: config.h:11
taco::TYPEALIGN
constexpr T TYPEALIGN(uint64_t ALIGNVAL, T LEN)
These alignment macros are derived from PostgreSQL.
Definition: tdb_base.h:320
taco::FieldId
int16_t FieldId
Definition: tdb_base.h:213
unique_malloced_ptr
std::unique_ptr< void, AlignedAllocImpl::FreeMem > unique_malloced_ptr
Definition: tdb_base.h:94
AlignedAllocImpl::aligned_allocator::operator!=
constexpr bool operator!=(const aligned_allocator &)
Definition: tdb_base.h:139
taco::TYPEALIGN_DOWN
constexpr T TYPEALIGN_DOWN(uint64_t ALIGNVAL, T LEN)
Definition: tdb_base.h:334
AlignedAllocImpl::aligned_allocator::allocate
static T * allocate(size_t n)
Definition: tdb_base.h:124
misc.h
AlignedAllocImpl::aligned_allocator::rebind::other
aligned_allocator< alignment, U > other
Definition: tdb_base.h:147
taco::MaxSlotId
constexpr SlotId MaxSlotId
The maximum valid slot ID.
Definition: tdb_base.h:265
CACHELINE_SIZE
constexpr const size_t CACHELINE_SIZE
Definition: tdb_base.h:158
AlignedAllocImpl::aligned_allocator::deallocate
static void deallocate(T *p, size_t)
Definition: tdb_base.h:129
fmgr.h
taco::AddWithCheck
bool AddWithCheck(T &left, U right)
Definition: tdb_base.h:347
AlignedAllocImpl::aligned_allocator::operator==
constexpr bool operator==(const aligned_allocator &)
Definition: tdb_base.h:134
maxaligned_char_buf
std::vector< char, AlignedAllocImpl::aligned_allocator< 8, char > > maxaligned_char_buf
Definition: tdb_base.h:155
taco::PageNumberBits
constexpr int PageNumberBits
Definition: tdb_base.h:228
taco::FileId
uint32_t FileId
The file ID.
Definition: tdb_base.h:222
taco::MaxOid
constexpr Oid MaxOid
The largest valid Oid.
Definition: tdb_base.h:282
taco::INVALID_BUFID
constexpr BufferId INVALID_BUFID
Definition: tdb_base.h:267
wrap_malloc
unique_malloced_ptr wrap_malloc(void *ptr)
Definition: tdb_base.h:106
L1_CACHELINE_SIZE
#define L1_CACHELINE_SIZE
Definition: config.h:8
taco::AggType
uint8_t AggType
The aggregation type, see catalog/aggtyp.h.
Definition: tdb_base.h:296
taco::Oid
uint32_t Oid
Definition: tdb_base.h:211
logging.h
config.h
AlignedAllocImpl
Definition: tdb_base.h:85
taco::InvalidOid
constexpr Oid InvalidOid
Definition: tdb_base.h:225
AlignedAllocImpl::aligned_allocator::difference_type
ptrdiff_t difference_type
Definition: tdb_base.h:121
AlignedAllocImpl::FreeMem::operator()
void operator()(void *x)
Definition: tdb_base.h:87
atomics.h
cast_as_string
std::enable_if<!std::is_same< typename std::decay< T >::type, absl::string_view >::value, T && >::type cast_as_string(T &&t)
This is intended for casting anything that represents a string in C++ to an std::string.
Definition: tdb_base.h:397
taco::FieldOffsetBits
constexpr int FieldOffsetBits
Definition: tdb_base.h:229
AlignedAllocImpl::aligned_allocator::value_type
T value_type
Definition: tdb_base.h:119
AlignedAllocImpl::aligned_allocator::size_type
size_t size_type
Definition: tdb_base.h:120
unique_malloc
unique_malloced_ptr unique_malloc(size_t size)
Definition: tdb_base.h:111
taco::MaxPageNumber
constexpr PageNumber MaxPageNumber
The maximum valid page number.
Definition: tdb_base.h:248
AlignedAllocImpl::aligned_allocator::rebind
Definition: tdb_base.h:146
taco::PageNumber
uint32_t PageNumber
Definition: tdb_base.h:214