├── .gitignore ├── masstree ├── masstree_btree.cc ├── AUTHORS ├── CMakeLists.txt ├── kvproto.hh ├── kvstats.hh ├── mtcounters.hh ├── LICENSE ├── timestamp.hh ├── compiler.cc ├── str.cc ├── GNUmakefile.in ├── hashcode.hh ├── masstree_get.hh ├── circular_int.hh ├── btree_leaflink.hh ├── str.hh └── masstree.hh ├── third-party ├── sparsehash │ └── src │ │ ├── stamp-h1 │ │ ├── config.h.include │ │ ├── sparsehash │ │ └── internal │ │ │ ├── sparseconfig.h │ │ │ └── libc_allocator_with_realloc.h │ │ ├── windows │ │ ├── google │ │ │ └── sparsehash │ │ │ │ └── sparseconfig.h │ │ ├── sparsehash │ │ │ └── internal │ │ │ │ └── sparseconfig.h │ │ ├── port.cc │ │ ├── port.h │ │ └── config.h │ │ ├── google │ │ ├── sparsetable │ │ ├── dense_hash_map │ │ ├── dense_hash_set │ │ ├── sparse_hash_map │ │ ├── sparse_hash_set │ │ ├── template_util.h │ │ ├── type_traits.h │ │ └── sparsehash │ │ │ ├── densehashtable.h │ │ │ ├── sparsehashtable.h │ │ │ ├── hashtable-common.h │ │ │ └── libc_allocator_with_realloc.h │ │ ├── config.h │ │ ├── config.h.in │ │ ├── template_util_unittest.cc │ │ └── libc_allocator_with_realloc_test.cc ├── glog │ └── lib │ │ ├── libglog.a │ │ ├── libglog.so │ │ ├── libglog.so.0 │ │ └── libglog.so.0.3.5 ├── gflags │ ├── lib │ │ ├── libgflags.a │ │ ├── libgflags.so │ │ ├── libgflags.so.2.2 │ │ ├── libgflags.so.2.2.2 │ │ ├── libgflags_nothreads.a │ │ ├── libgflags_nothreads.so │ │ ├── libgflags_nothreads.so.2.2 │ │ └── libgflags_nothreads.so.2.2.2 │ └── include │ │ └── gflags │ │ ├── defines.h │ │ └── gflags_gflags.h └── foedus │ ├── zipfian_random.hpp │ └── uniform_random.hpp ├── dbcore ├── .gitignore ├── sm-coroutine.cpp ├── mcs_lock.cpp ├── tests │ ├── CMakeLists.txt │ ├── test-xid.cpp │ ├── test-epoch.cpp │ ├── test-dynarray.cpp │ ├── test-cslist.cpp │ ├── test-window-buffer.cpp │ ├── test-size-encode.cpp │ ├── test-sm-oid.cpp │ └── w_rand.cpp ├── ring-buff-queue.h ├── stopwatch.h ├── sm-exceptions.cpp ├── sm-spinlock.h ├── sm-common.cpp ├── sm-rc.h ├── sm-spinlock.cpp ├── CMakeLists.txt ├── dlog-tx.h ├── sm-table.cpp ├── burt-hash.h ├── pcommit.h ├── size-encode.h ├── sm-table.h ├── pcommit.cpp ├── serial.h ├── dlog-defs.h ├── stub-impl.h ├── sm-config.cpp ├── sm-object.h ├── defer.h └── burt-hash.py ├── benchmarks ├── record │ └── CMakeLists.txt ├── dbtest.h ├── CMakeLists.txt └── tpcc │ └── CMakeLists.txt ├── tuple.cc ├── macros.h ├── LICENSE ├── varstr.h ├── str_arena.h ├── engine_internal.h ├── txn-mvocc.cc └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /masstree/masstree_btree.cc: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/stamp-h1: -------------------------------------------------------------------------------- 1 | timestamp for src/config.h 2 | -------------------------------------------------------------------------------- /dbcore/.gitignore: -------------------------------------------------------------------------------- 1 | ; automatically generating files 2 | burt-hash.cpp 3 | -------------------------------------------------------------------------------- /benchmarks/record/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set_property(GLOBAL APPEND PROPERTY ALL_SRC 2 | ) 3 | -------------------------------------------------------------------------------- /third-party/glog/lib/libglog.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfu-dis/preemptdb/HEAD/third-party/glog/lib/libglog.a -------------------------------------------------------------------------------- /third-party/glog/lib/libglog.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfu-dis/preemptdb/HEAD/third-party/glog/lib/libglog.so -------------------------------------------------------------------------------- /third-party/gflags/lib/libgflags.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfu-dis/preemptdb/HEAD/third-party/gflags/lib/libgflags.a -------------------------------------------------------------------------------- /third-party/gflags/lib/libgflags.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfu-dis/preemptdb/HEAD/third-party/gflags/lib/libgflags.so -------------------------------------------------------------------------------- /third-party/glog/lib/libglog.so.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfu-dis/preemptdb/HEAD/third-party/glog/lib/libglog.so.0 -------------------------------------------------------------------------------- /third-party/glog/lib/libglog.so.0.3.5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfu-dis/preemptdb/HEAD/third-party/glog/lib/libglog.so.0.3.5 -------------------------------------------------------------------------------- /third-party/gflags/lib/libgflags.so.2.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfu-dis/preemptdb/HEAD/third-party/gflags/lib/libgflags.so.2.2 -------------------------------------------------------------------------------- /third-party/gflags/lib/libgflags.so.2.2.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfu-dis/preemptdb/HEAD/third-party/gflags/lib/libgflags.so.2.2.2 -------------------------------------------------------------------------------- /third-party/gflags/lib/libgflags_nothreads.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfu-dis/preemptdb/HEAD/third-party/gflags/lib/libgflags_nothreads.a -------------------------------------------------------------------------------- /third-party/gflags/lib/libgflags_nothreads.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfu-dis/preemptdb/HEAD/third-party/gflags/lib/libgflags_nothreads.so -------------------------------------------------------------------------------- /masstree/AUTHORS: -------------------------------------------------------------------------------- 1 | Eddie Kohler 2 | kohler@seas.harvard.edu 3 | 4 | Yandong Mao 5 | ydmao@csail.mit.edu 6 | 7 | Robert Morris 8 | rtm@csail.mit.edu 9 | -------------------------------------------------------------------------------- /third-party/gflags/lib/libgflags_nothreads.so.2.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfu-dis/preemptdb/HEAD/third-party/gflags/lib/libgflags_nothreads.so.2.2 -------------------------------------------------------------------------------- /third-party/gflags/lib/libgflags_nothreads.so.2.2.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sfu-dis/preemptdb/HEAD/third-party/gflags/lib/libgflags_nothreads.so.2.2.2 -------------------------------------------------------------------------------- /benchmarks/dbtest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "bench.h" 5 | 6 | void bench_main(int argc, char **argv, std::function test_fn); 7 | -------------------------------------------------------------------------------- /benchmarks/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(record) 2 | 3 | set_property(GLOBAL APPEND PROPERTY ALL_SRC 4 | ${CMAKE_CURRENT_SOURCE_DIR}/bench.cc 5 | ${CMAKE_CURRENT_SOURCE_DIR}/dbtest.cc 6 | ) 7 | 8 | -------------------------------------------------------------------------------- /dbcore/sm-coroutine.cpp: -------------------------------------------------------------------------------- 1 | #include "sm-coroutine.h" 2 | 3 | namespace ermia { 4 | namespace coro { 5 | 6 | thread_local tcalloc coroutine_allocator; // TODO(pcontext?): leave it as-is for now until we need to support coroutine 7 | 8 | } // namespace coro 9 | } // namespace ermia 10 | -------------------------------------------------------------------------------- /masstree/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set_property(GLOBAL APPEND PROPERTY ALL_SRC 2 | ${CMAKE_CURRENT_SOURCE_DIR}/masstree_btree.cc 3 | ${CMAKE_CURRENT_SOURCE_DIR}/compiler.cc 4 | ${CMAKE_CURRENT_SOURCE_DIR}/straccum.cc 5 | ${CMAKE_CURRENT_SOURCE_DIR}/str.cc 6 | ${CMAKE_CURRENT_SOURCE_DIR}/string.cc 7 | ) 8 | -------------------------------------------------------------------------------- /dbcore/mcs_lock.cpp: -------------------------------------------------------------------------------- 1 | #include "mcs_lock.h" 2 | 3 | void mcs_lock::spin_on_waiting(qnode* me) { 4 | while (me->vthis()->_waiting) 5 | ; 6 | } 7 | 8 | mcs_lock::qnode* mcs_lock::spin_on_next(qnode* me) { 9 | qnode* next; 10 | while (!(next = me->vthis()->_next)) 11 | ; 12 | return next; 13 | } 14 | -------------------------------------------------------------------------------- /tuple.cc: -------------------------------------------------------------------------------- 1 | #include "txn.h" 2 | #include "tuple.h" 3 | 4 | namespace ermia { 5 | 6 | #ifdef SSN 7 | bool dbtuple::is_old(TXN::xid_context *visitor) { // FOR READERS ONLY! 8 | return visitor->xct->is_read_mostly() && 9 | age(visitor) >= config::ssn_read_opt_threshold; 10 | } 11 | #endif 12 | } // namespace ermia 13 | -------------------------------------------------------------------------------- /benchmarks/tpcc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set_property(GLOBAL APPEND PROPERTY ALL_SRC 2 | ${CMAKE_CURRENT_SOURCE_DIR}/tpcc-config.cc 3 | ${CMAKE_CURRENT_SOURCE_DIR}/../bench.cc 4 | ${CMAKE_CURRENT_SOURCE_DIR}/../dbtest.cc 5 | ) 6 | 7 | add_executable(tpcc_SI_sequential ${CMAKE_CURRENT_SOURCE_DIR}/tpcc-sequential.cc) 8 | set_target_properties(tpcc_SI_sequential PROPERTIES COMPILE_FLAGS "") 9 | target_link_libraries(tpcc_SI_sequential preemptdb_si thread_pool) 10 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/config.h.include: -------------------------------------------------------------------------------- 1 | /*** 2 | *** These are #defines that autoheader puts in config.h.in that we 3 | *** want to show up in sparseconfig.h, the minimal config.h file 4 | *** #included by all our .h files. The reason we don't take 5 | *** everything that autoheader emits is that we have to include a 6 | *** config.h in installed header files, and we want to minimize the 7 | *** number of #defines we make so as to not pollute the namespace. 8 | ***/ 9 | GOOGLE_NAMESPACE 10 | HASH_NAMESPACE 11 | HASH_FUN_H 12 | SPARSEHASH_HASH 13 | HAVE_UINT16_T 14 | HAVE_U_INT16_T 15 | HAVE___UINT16 16 | HAVE_LONG_LONG 17 | HAVE_SYS_TYPES_H 18 | HAVE_STDINT_H 19 | HAVE_INTTYPES_H 20 | HAVE_MEMCPY 21 | _END_GOOGLE_NAMESPACE_ 22 | _START_GOOGLE_NAMESPACE_ 23 | -------------------------------------------------------------------------------- /dbcore/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # TODO(tzwang): generate executables for test cases below 2 | #${CMAKE_CURRENT_SOURCE_DIR}/w_rand.cpp 3 | #${CMAKE_CURRENT_SOURCE_DIR}/test-adler.cpp 4 | #${CMAKE_CURRENT_SOURCE_DIR}/test-dynarray.cpp 5 | #${CMAKE_CURRENT_SOURCE_DIR}/test-epoch.cpp 6 | #${CMAKE_CURRENT_SOURCE_DIR}/test-sc-hash.cpp 7 | #${CMAKE_CURRENT_SOURCE_DIR}/test-size-encode.cpp 8 | #${CMAKE_CURRENT_SOURCE_DIR}/test-sm-log-alloc.cpp 9 | #${CMAKE_CURRENT_SOURCE_DIR}/test-sm-log.cpp 10 | #${CMAKE_CURRENT_SOURCE_DIR}/test-sm-log-file.cpp 11 | #${CMAKE_CURRENT_SOURCE_DIR}/test-sm-log-offset.cpp 12 | #${CMAKE_CURRENT_SOURCE_DIR}/test-sm-oid-alloc-impl.cpp 13 | #${CMAKE_CURRENT_SOURCE_DIR}/test-sm-oid.cpp 14 | #${CMAKE_CURRENT_SOURCE_DIR}/test-window-buffer.cpp 15 | #${CMAKE_CURRENT_SOURCE_DIR}/test-xid.cpp 16 | 17 | -------------------------------------------------------------------------------- /dbcore/ring-buff-queue.h: -------------------------------------------------------------------------------- 1 | template 2 | class OneToOneQueue{ 3 | 4 | T *data; 5 | volatile uint32_t startIdx{0}; 6 | volatile uint32_t endIdx{0}; 7 | uint32_t capacity; 8 | public: 9 | OneToOneQueue() = default; 10 | OneToOneQueue(OneToOneQueue&& q) = delete; 11 | 12 | void init(uint32_t _capacity){ 13 | this->capacity = _capacity + 1; 14 | data = new T[capacity]; 15 | } 16 | 17 | ~OneToOneQueue(){ 18 | delete[] data; 19 | } 20 | 21 | bool isEmpty(){ 22 | return startIdx == endIdx; 23 | } 24 | 25 | bool isFull(){ 26 | return (endIdx + 1) % capacity == startIdx; 27 | } 28 | 29 | void pop(){ 30 | startIdx = (startIdx + 1) % capacity; 31 | } 32 | 33 | T front(){ 34 | return data[startIdx]; 35 | } 36 | 37 | void push(T t){ 38 | data[endIdx] = t; 39 | endIdx = (endIdx + 1) % capacity; 40 | } 41 | 42 | }; -------------------------------------------------------------------------------- /dbcore/stopwatch.h: -------------------------------------------------------------------------------- 1 | /* -*- mode:C++; c-basic-offset:4 -*- */ 2 | 3 | #ifndef _STOPWATCH_H 4 | #define _STOPWATCH_H 5 | 6 | #include 7 | #include 8 | 9 | /** 10 | * @brief a timer object. 11 | */ 12 | class stopwatch_t { 13 | private: 14 | uint64_t _mark; 15 | 16 | public: 17 | stopwatch_t() { reset(); } 18 | uint64_t time_ns() { 19 | uint64_t old_mark = _mark; 20 | return reset() - old_mark; 21 | } 22 | double time_us() { return time_ns() * 1e-3; } 23 | double time_ms() { return time_ns() * 1e-6; } 24 | double time() { return time_ns() * 1e-9; } 25 | 26 | /* reads the clock without storing the result */ 27 | static uint64_t now() { 28 | struct timespec tv; 29 | clock_gettime(CLOCK_REALTIME, &tv); 30 | return tv.tv_nsec + tv.tv_sec * 1000000000ll; 31 | } 32 | 33 | /* returns whatever was last read */ 34 | uint64_t mark() const { return _mark; } 35 | 36 | operator uint64_t() const { return mark(); } 37 | 38 | /* reads the clock and sets the mark to match */ 39 | uint64_t reset() { return _mark = now(); } 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /macros.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define USE_VARINT_ENCODING 4 | 5 | #define LG_CACHELINE_SIZE __builtin_ctz(CACHELINE_SIZE) 6 | 7 | // some helpers for cacheline alignment 8 | #define CACHE_ALIGNED __attribute__((aligned(CACHELINE_SIZE))) 9 | 10 | #define __XCONCAT2(a, b) a ## b 11 | #define __XCONCAT(a, b) __XCONCAT2(a, b) 12 | #define CACHE_PADOUT \ 13 | char __XCONCAT(__padout, __COUNTER__)[0] __attribute__((aligned(CACHELINE_SIZE))) 14 | #define PACKED __attribute__((packed)) 15 | 16 | #ifndef ALWAYS_INLINE 17 | #define ALWAYS_INLINE __attribute__((always_inline)) inline 18 | #endif 19 | 20 | #define likely(x) __builtin_expect(!!(x), 1) 21 | #define unlikely(x) __builtin_expect(!!(x), 0) 22 | 23 | #ifndef ALWAYS_ASSERT 24 | #define ALWAYS_ASSERT(expr) (likely((expr)) ? (void)0 : abort()) 25 | #endif 26 | 27 | #define MARK_REFERENCED(x) (void)x 28 | 29 | #define COMPILER_MEMORY_FENCE asm volatile("" ::: "memory") 30 | 31 | #define ARRAY_NELEMS(a) (sizeof(a)/sizeof((a)[0])) 32 | 33 | #define VERBOSE(expr) ((void)0) 34 | //#define VERBOSE(expr) (expr) 35 | 36 | #define NOP_PAUSE asm volatile("pause" : :) 37 | -------------------------------------------------------------------------------- /dbcore/sm-exceptions.cpp: -------------------------------------------------------------------------------- 1 | #include "sm-exceptions.h" 2 | 3 | #include "sm-common.h" 4 | 5 | #include 6 | #include 7 | 8 | illegal_argument::illegal_argument(char const volatile *m, ...) { 9 | va_list ap; 10 | va_start(ap, m); 11 | DEFER(va_end(ap)); 12 | 13 | int err = vasprintf(&free_msg, (char const *)m, ap); 14 | if (err < 0) { 15 | msg = ""; 16 | free_msg = 0; 17 | } else { 18 | msg = free_msg; 19 | } 20 | } 21 | 22 | os_error::os_error(int e, char const volatile *m, ...) : err(e) { 23 | va_list ap; 24 | va_start(ap, m); 25 | DEFER(va_end(ap)); 26 | 27 | int err = vasprintf(&free_msg, (char const *)m, ap); 28 | if (err < 0) { 29 | msg = ""; 30 | free_msg = 0; 31 | } else { 32 | msg = free_msg; 33 | } 34 | } 35 | 36 | log_file_error::log_file_error(char const volatile *m, ...) { 37 | va_list ap; 38 | va_start(ap, m); 39 | DEFER(va_end(ap)); 40 | 41 | int err = vasprintf(&free_msg, (char const *)m, ap); 42 | if (err < 0) { 43 | msg = ""; 44 | free_msg = 0; 45 | } else { 46 | msg = free_msg; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /dbcore/tests/test-xid.cpp: -------------------------------------------------------------------------------- 1 | #include "xid.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | bool done = false; 8 | 9 | extern "C" void* slow_worker(void* t) { 10 | size_t tid = (size_t)t; 11 | while (not volatile_read(done)) { 12 | XID xid = xid_alloc(); 13 | printf("%.10u %.4u\n", xid.epoch(), xid.local()); 14 | usleep(1000); 15 | xid_get_context(xid); 16 | xid_free(xid); 17 | } 18 | return NULL; 19 | } 20 | 21 | extern "C" void* fast_worker(void* t) { 22 | size_t tid = (size_t)t; 23 | while (not volatile_read(done)) { 24 | XID xid = xid_alloc(); 25 | printf("%.10u %.4u\n", xid.epoch(), xid.local()); 26 | usleep(10); 27 | xid_get_context(xid); 28 | xid_free(xid); 29 | } 30 | return NULL; 31 | } 32 | 33 | int main() { 34 | pthread_t fast_thd[4], slow_thd; 35 | 36 | fprintf(stderr, "Creating worker threads\n"); 37 | pthread_create(&slow_thd, NULL, slow_worker, (void*)-1); 38 | for (auto it : enumerate(fast_thd)) 39 | pthread_create(&it.second, NULL, fast_worker, (void*)it.first); 40 | 41 | fprintf(stderr, "Sleeping for 10 seconds...\n"); 42 | sleep(10); 43 | fprintf(stderr, "... back, joining with workers\n"); 44 | done = true; 45 | 46 | for (auto t : fast_thd) pthread_join(t, NULL); 47 | pthread_join(slow_thd, NULL); 48 | fprintf(stderr, "Done!\n"); 49 | } 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2024 Kaisong Huang, Jiatang Zhou, Zhuoyue Zhao, Dong Xie, and Tianzheng Wang 4 | Copyright (C) 2020 Yongjun He and Tianzheng Wang 5 | Copyright (C) 2015 Kangnyeon Kim, Tianzheng Wang, Ryan Johnson and Ippokratis Pandis 6 | Copyright (C) 2013 Stephen Tu and other contributors 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | -------------------------------------------------------------------------------- /dbcore/sm-spinlock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "sm-coroutine.h" 8 | 9 | #define MIN_DELAY_MICROSEC 1L 10 | 11 | #define DELAY(n) \ 12 | do { \ 13 | volatile int x = 0; \ 14 | for (int i = 0; i < (n); ++i) x++; \ 15 | } while (0) 16 | 17 | constexpr int kExpBackoffBase = 4000; 18 | constexpr int kExpBackoffLimit = 32000; 19 | constexpr int kExpBackoffMultiplier = 2; 20 | 21 | namespace ermia { 22 | void microdelay(long microsec); 23 | 24 | class TATAS { 25 | std::atomic lock_; 26 | uint64_t attempt; 27 | uint64_t success; 28 | public: 29 | TATAS() { 30 | std::atomic_init(&lock_, 0ull); 31 | attempt = 0; 32 | success = 0; 33 | } 34 | void lock(); 35 | void unlock(); 36 | uint64_t get_attempt(); 37 | uint64_t get_success(); 38 | }; 39 | 40 | class Spinlock { 41 | private: 42 | std::atomic_flag flag; 43 | 44 | public: 45 | Spinlock() : flag(ATOMIC_FLAG_INIT) {} 46 | 47 | void lock() { 48 | while (flag.test_and_set(std::memory_order_acquire)) { 49 | // busy spin until the flag is cleared 50 | } 51 | } 52 | 53 | void unlock() { 54 | flag.clear(std::memory_order_release); 55 | } 56 | }; 57 | } 58 | -------------------------------------------------------------------------------- /dbcore/sm-common.cpp: -------------------------------------------------------------------------------- 1 | #include "sm-common.h" 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace ermia { 14 | 15 | int os_dup(int fd) { 16 | int rval = dup(fd); 17 | THROW_IF(rval < 0, os_error, errno, "Unable to duplicate fd %d", fd); 18 | return rval; 19 | } 20 | 21 | dirent_iterator::dirent_iterator(char const *dname) 22 | : _d(opendir(dname)), used(false) { 23 | THROW_IF(not _d, os_error, errno, "Unable to open/create directory: %s", 24 | dname); 25 | } 26 | 27 | dirent_iterator::~dirent_iterator() { 28 | int err = closedir(_d); 29 | WARN_IF(err, "Closing dirent iterator gave errno %d", errno); 30 | } 31 | 32 | void dirent_iterator::iterator::operator++() { 33 | errno = 0; 34 | _dent = readdir(_d); 35 | if (not _dent) { 36 | THROW_IF(errno, os_error, errno, "Error during directory scan"); 37 | _d = NULL; 38 | } 39 | } 40 | 41 | dirent_iterator::iterator dirent_iterator::begin() { 42 | if (used) rewinddir(_d); 43 | 44 | used = true; 45 | iterator rval{_d, NULL}; 46 | ++rval; // prime it 47 | return rval; 48 | } 49 | 50 | dirent_iterator::iterator dirent_iterator::end() { 51 | return iterator{NULL, NULL}; 52 | } 53 | 54 | int dirent_iterator::dup() { return os_dup(dirfd(_d)); } 55 | } // namespace ermia 56 | -------------------------------------------------------------------------------- /dbcore/sm-rc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | // 8 bits for return code: 5 | // bit meaning 6 | // 8 user requested abort 7 | // 7 there's phantom, tx should abort 8 | // 6 abort due to rw conflict with the read optimization 9 | // 5 SSN/SSI determines tx should abort 10 | // 4 should abort due to SI conflict (first writer wins) 11 | // 3 tx should abort due to internal error (eg got an invalid cstamp) 12 | // 2 abort marker - must be used in conjunction with one of the detailed 13 | // reasons 14 | // 1 false (e.g., read a deleted tuple) 15 | // 0 true (success) 16 | // 17 | // NOTE: SSN/SSI/SI abort code will also have 18 | // the ABORT bit set for easier checking 19 | 20 | #define RC_INVALID 0x0 21 | #define RC_TRUE 0x1 22 | #define RC_FALSE 0x2 23 | #define RC_ABORT 0x4 24 | #define RC_ABORT_INTERNAL (RC_ABORT | 0x8) 25 | #define RC_ABORT_SI_CONFLICT (RC_ABORT | 0x10) 26 | #define RC_ABORT_SERIAL (RC_ABORT | 0x20) 27 | #define RC_ABORT_RW_CONFLICT (RC_ABORT | 0x40) 28 | #define RC_ABORT_PHANTOM (RC_ABORT | 0x80) 29 | #define RC_ABORT_USER (RC_ABORT | 0x100) 30 | 31 | // Operation (e.g., r/w) return code 32 | struct rc_t { 33 | uint16_t _val; 34 | 35 | rc_t() : _val(RC_INVALID) {} 36 | rc_t(uint16_t v) : _val(v) {} 37 | 38 | inline bool IsUserAbort() { return _val == RC_ABORT_USER; } 39 | inline bool IsInvalid() { return _val == RC_INVALID; } 40 | inline bool IsAbort() { return _val & RC_ABORT; } 41 | }; 42 | 43 | 44 | -------------------------------------------------------------------------------- /dbcore/sm-spinlock.cpp: -------------------------------------------------------------------------------- 1 | #include "sm-spinlock.h" 2 | 3 | namespace ermia { 4 | void microdelay(long microsec) { 5 | if (microsec > 0) { 6 | struct timeval delay; 7 | delay.tv_sec = microsec / 1000000L; 8 | delay.tv_usec = microsec % 1000000L; 9 | (void) select(0, NULL, NULL, NULL, &delay); 10 | } 11 | } 12 | 13 | void TATAS::lock() { 14 | int cas_failure = 0; 15 | uint64_t seed = (uintptr_t)(&cas_failure); 16 | auto next_u32 = [&]() { 17 | seed = seed * 0xD04C3175 + 0x53DA9022; 18 | return (seed >> 32) ^ (seed & 0xFFFFFFFF); 19 | }; 20 | next_u32(); 21 | int maxDelay = kExpBackoffBase; 22 | retry: 23 | auto locked = lock_.load(std::memory_order_acquire); 24 | if (locked) { 25 | int delay = next_u32() % maxDelay; 26 | maxDelay = std::min(maxDelay * kExpBackoffMultiplier, kExpBackoffLimit); 27 | DELAY(delay); 28 | goto retry; 29 | } 30 | 31 | if (!lock_.compare_exchange_strong(locked, 1ul)) { 32 | cas_failure++; 33 | int delay = next_u32() % maxDelay; 34 | maxDelay = std::min(maxDelay * kExpBackoffMultiplier, kExpBackoffLimit); 35 | DELAY(delay); 36 | goto retry; 37 | } 38 | } 39 | 40 | void TATAS::unlock() { 41 | lock_.store(0, std::memory_order_release); 42 | } 43 | 44 | uint64_t TATAS::get_attempt() { 45 | return attempt; 46 | } 47 | 48 | uint64_t TATAS::get_success() { 49 | return success; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /dbcore/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Generate burt-hash.cpp 2 | if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/burt-hash.cpp") 3 | set(BURT_HASH_GEN python2 ${CMAKE_CURRENT_SOURCE_DIR}/burt-hash.py) 4 | execute_process(COMMAND ${BURT_HASH_GEN} ERROR_VARIABLE out OUTPUT_VARIABLE out) 5 | if ("${out}" STREQUAL "") 6 | message(FATAL_ERROR "Generating burt-hash.cpp failed. Please make sure python2 is installed.") 7 | else() 8 | file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/burt-hash.cpp "${out}") 9 | endif() 10 | endif() 11 | 12 | set(DBCORE_SRC 13 | ${CMAKE_CURRENT_SOURCE_DIR}/burt-hash.cpp 14 | ${CMAKE_CURRENT_SOURCE_DIR}/dlog.cpp 15 | ${CMAKE_CURRENT_SOURCE_DIR}/dynarray.cpp 16 | ${CMAKE_CURRENT_SOURCE_DIR}/epoch.cpp 17 | ${CMAKE_CURRENT_SOURCE_DIR}/mcs_lock.cpp 18 | ${CMAKE_CURRENT_SOURCE_DIR}/pcommit.cpp 19 | ${CMAKE_CURRENT_SOURCE_DIR}/serial.cpp 20 | ${CMAKE_CURRENT_SOURCE_DIR}/size-encode.cpp 21 | ${CMAKE_CURRENT_SOURCE_DIR}/sm-alloc.cpp 22 | ${CMAKE_CURRENT_SOURCE_DIR}/sm-common.cpp 23 | ${CMAKE_CURRENT_SOURCE_DIR}/sm-config.cpp 24 | ${CMAKE_CURRENT_SOURCE_DIR}/sm-coroutine.cpp 25 | ${CMAKE_CURRENT_SOURCE_DIR}/sm-exceptions.cpp 26 | ${CMAKE_CURRENT_SOURCE_DIR}/sm-table.cpp 27 | ${CMAKE_CURRENT_SOURCE_DIR}/sm-object.cpp 28 | ${CMAKE_CURRENT_SOURCE_DIR}/sm-oid-alloc.cpp 29 | ${CMAKE_CURRENT_SOURCE_DIR}/sm-oid.cpp 30 | ${CMAKE_CURRENT_SOURCE_DIR}/sm-spinlock.cpp 31 | ${CMAKE_CURRENT_SOURCE_DIR}/xid.cpp 32 | ) 33 | 34 | set_property(GLOBAL APPEND PROPERTY ALL_SRC ${DBCORE_SRC}) 35 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/sparsehash/internal/sparseconfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * NOTE: This file is for internal use only. 3 | * Do not use these #defines in your own program! 4 | */ 5 | 6 | /* Namespace for Google classes */ 7 | #define GOOGLE_NAMESPACE ::google 8 | 9 | /* the location of the header defining hash functions */ 10 | #define HASH_FUN_H 11 | 12 | /* the namespace of the hash<> function */ 13 | #define HASH_NAMESPACE std 14 | 15 | /* Define to 1 if you have the header file. */ 16 | #define HAVE_INTTYPES_H 1 17 | 18 | /* Define to 1 if the system has the type `long long'. */ 19 | #define HAVE_LONG_LONG 1 20 | 21 | /* Define to 1 if you have the `memcpy' function. */ 22 | #define HAVE_MEMCPY 1 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #define HAVE_STDINT_H 1 26 | 27 | /* Define to 1 if you have the header file. */ 28 | #define HAVE_SYS_TYPES_H 1 29 | 30 | /* Define to 1 if the system has the type `uint16_t'. */ 31 | #define HAVE_UINT16_T 1 32 | 33 | /* Define to 1 if the system has the type `u_int16_t'. */ 34 | #define HAVE_U_INT16_T 1 35 | 36 | /* Define to 1 if the system has the type `__uint16'. */ 37 | /* #undef HAVE___UINT16 */ 38 | 39 | /* The system-provided hash function including the namespace. */ 40 | #define SPARSEHASH_HASH HASH_NAMESPACE::hash 41 | 42 | /* Stops putting the code inside the Google namespace */ 43 | #define _END_GOOGLE_NAMESPACE_ } 44 | 45 | /* Puts following code inside the Google namespace */ 46 | #define _START_GOOGLE_NAMESPACE_ namespace google { 47 | -------------------------------------------------------------------------------- /third-party/gflags/include/gflags/defines.h: -------------------------------------------------------------------------------- 1 | /* Generated from defines.h.in during build configuration using CMake. */ 2 | 3 | // Note: This header file is only used internally. It is not part of public interface! 4 | // Any cmakedefine is defined using the -D flag instead when Bazel is used. 5 | // For Bazel, this file is thus not used to avoid a private file in $(GENDIR). 6 | 7 | #ifndef GFLAGS_DEFINES_H_ 8 | #define GFLAGS_DEFINES_H_ 9 | 10 | 11 | // Define if you build this library for a MS Windows OS. 12 | /* #undef OS_WINDOWS */ 13 | 14 | // Define if you have the header file. 15 | #define HAVE_STDINT_H 16 | 17 | // Define if you have the header file. 18 | #define HAVE_SYS_TYPES_H 19 | 20 | // Define if you have the header file. 21 | #define HAVE_INTTYPES_H 22 | 23 | // Define if you have the header file. 24 | #define HAVE_SYS_STAT_H 25 | 26 | // Define if you have the header file. 27 | #define HAVE_UNISTD_H 28 | 29 | // Define if you have the header file. 30 | #define HAVE_FNMATCH_H 31 | 32 | // Define if you have the header file (Windows 2000/XP). 33 | /* #undef HAVE_SHLWAPI_H */ 34 | 35 | // Define if you have the strtoll function. 36 | #define HAVE_STRTOLL 37 | 38 | // Define if you have the strtoq function. 39 | /* #undef HAVE_STRTOQ */ 40 | 41 | // Define if you have the header file. 42 | #define HAVE_PTHREAD 43 | 44 | // Define if your pthread library defines the type pthread_rwlock_t 45 | #define HAVE_RWLOCK 46 | 47 | 48 | #endif // GFLAGS_DEFINES_H_ 49 | -------------------------------------------------------------------------------- /masstree/kvproto.hh: -------------------------------------------------------------------------------- 1 | /* Masstree 2 | * Eddie Kohler, Yandong Mao, Robert Morris 3 | * Copyright (c) 2012-2013 President and Fellows of Harvard College 4 | * Copyright (c) 2012-2013 Massachusetts Institute of Technology 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, subject to the conditions 9 | * listed in the Masstree LICENSE file. These conditions include: you must 10 | * preserve this copyright notice, and you cannot mention the copyright 11 | * holders in advertising related to the Software without their permission. 12 | * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This 13 | * notice is a summary of the Masstree LICENSE file; the license in that file 14 | * is legally binding. 15 | */ 16 | #ifndef KVPROTO_HH 17 | #define KVPROTO_HH 18 | #include "compiler.hh" 19 | 20 | enum { 21 | Cmd_None = 0, 22 | Cmd_Get = 2, 23 | Cmd_Scan = 4, 24 | Cmd_Put = 6, 25 | Cmd_Replace = 8, 26 | Cmd_Remove = 10, 27 | Cmd_Checkpoint = 12, 28 | Cmd_Handshake = 14, 29 | Cmd_Max 30 | }; 31 | 32 | enum result_t { 33 | NotFound = -2, 34 | Retry, 35 | OutOfDate, 36 | Inserted, 37 | Updated, 38 | Found, 39 | ScanDone 40 | }; 41 | 42 | enum ckptrav_order_t { ckptrav_inorder = 0, ckptrav_preorder }; 43 | 44 | struct row_marker { 45 | enum { mt_remove = 1, mt_delta = 2 }; 46 | int marker_type_; 47 | }; 48 | 49 | template 50 | inline bool row_is_marker(const R* row) { 51 | return row->timestamp() & 1; 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/windows/google/sparsehash/sparseconfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * NOTE: This file is for internal use only. 3 | * Do not use these #defines in your own program! 4 | */ 5 | 6 | /* Namespace for Google classes */ 7 | #define GOOGLE_NAMESPACE ::google 8 | 9 | /* the location of the header defining hash functions */ 10 | #define HASH_FUN_H 11 | 12 | /* the namespace of the hash<> function */ 13 | #define HASH_NAMESPACE stdext 14 | 15 | /* Define to 1 if you have the header file. */ 16 | #undef HAVE_INTTYPES_H 17 | 18 | /* Define to 1 if the system has the type `long long'. */ 19 | #define HAVE_LONG_LONG 1 20 | 21 | /* Define to 1 if you have the `memcpy' function. */ 22 | #define HAVE_MEMCPY 1 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #undef HAVE_STDINT_H 26 | 27 | /* Define to 1 if you have the header file. */ 28 | #define HAVE_SYS_TYPES_H 1 29 | 30 | /* Define to 1 if the system has the type `uint16_t'. */ 31 | #undef HAVE_UINT16_T 32 | 33 | /* Define to 1 if the system has the type `u_int16_t'. */ 34 | #undef HAVE_U_INT16_T 35 | 36 | /* Define to 1 if the system has the type `__uint16'. */ 37 | #define HAVE___UINT16 1 38 | 39 | /* The system-provided hash function including the namespace. */ 40 | #define SPARSEHASH_HASH HASH_NAMESPACE::hash_compare 41 | 42 | /* The system-provided hash function, in namespace HASH_NAMESPACE. */ 43 | #define SPARSEHASH_HASH_NO_NAMESPACE hash_compare 44 | 45 | /* Stops putting the code inside the Google namespace */ 46 | #define _END_GOOGLE_NAMESPACE_ } 47 | 48 | /* Puts following code inside the Google namespace */ 49 | #define _START_GOOGLE_NAMESPACE_ namespace google { 50 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/windows/sparsehash/internal/sparseconfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * NOTE: This file is for internal use only. 3 | * Do not use these #defines in your own program! 4 | */ 5 | 6 | /* Namespace for Google classes */ 7 | #define GOOGLE_NAMESPACE ::google 8 | 9 | /* the location of the header defining hash functions */ 10 | #define HASH_FUN_H 11 | 12 | /* the namespace of the hash<> function */ 13 | #define HASH_NAMESPACE stdext 14 | 15 | /* Define to 1 if you have the header file. */ 16 | #undef HAVE_INTTYPES_H 17 | 18 | /* Define to 1 if the system has the type `long long'. */ 19 | #define HAVE_LONG_LONG 1 20 | 21 | /* Define to 1 if you have the `memcpy' function. */ 22 | #define HAVE_MEMCPY 1 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #undef HAVE_STDINT_H 26 | 27 | /* Define to 1 if you have the header file. */ 28 | #define HAVE_SYS_TYPES_H 1 29 | 30 | /* Define to 1 if the system has the type `uint16_t'. */ 31 | #undef HAVE_UINT16_T 32 | 33 | /* Define to 1 if the system has the type `u_int16_t'. */ 34 | #undef HAVE_U_INT16_T 35 | 36 | /* Define to 1 if the system has the type `__uint16'. */ 37 | #define HAVE___UINT16 1 38 | 39 | /* The system-provided hash function including the namespace. */ 40 | #define SPARSEHASH_HASH HASH_NAMESPACE::hash_compare 41 | 42 | /* The system-provided hash function, in namespace HASH_NAMESPACE. */ 43 | #define SPARSEHASH_HASH_NO_NAMESPACE hash_compare 44 | 45 | /* Stops putting the code inside the Google namespace */ 46 | #define _END_GOOGLE_NAMESPACE_ } 47 | 48 | /* Puts following code inside the Google namespace */ 49 | #define _START_GOOGLE_NAMESPACE_ namespace google { 50 | -------------------------------------------------------------------------------- /dbcore/tests/test-epoch.cpp: -------------------------------------------------------------------------------- 1 | #include "epoch.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define LOG(msg, ...) fprintf(stderr, msg "\n", ##__VA_ARGS__) 8 | 9 | size_t x = 1; 10 | 11 | void global_init(void *arg) { LOG("Initializing"); } 12 | epoch_mgr::cls_storage *get_cls(void *) { 13 | static __thread epoch_mgr::cls_storage s; 14 | return &s; 15 | } 16 | void *context_registered(void *) { 17 | LOG("Context %zd registered", (size_t)pthread_self()); 18 | return 0; 19 | } 20 | void context_deregistered(void *cookie, void *context_cookie) { 21 | LOG("Context %zd deregistered", (size_t)pthread_self()); 22 | } 23 | void *epoch_ended(void *, epoch_mgr::epoch_num x) { 24 | LOG("Epoch %zd ended", x); 25 | return (void *)x; 26 | } 27 | 28 | void *epoch_ended_context(void *cookie, void *epoch_cookie, 29 | void *context_cookie) { 30 | return epoch_cookie; 31 | } 32 | void epoch_reclaimed(void *cookie, void *epoch_cookie) { 33 | LOG("Epoch %zd reclaimed", (size_t)epoch_cookie); 34 | } 35 | 36 | struct state {}; 37 | 38 | static state s; 39 | 40 | static epoch_mgr em{{&s, &global_init, &get_cls, &context_registered, 41 | &context_deregistered, &epoch_ended, &epoch_ended_context, 42 | &epoch_reclaimed}}; 43 | 44 | int main() { 45 | em.context_init(); 46 | LOG("context_enter"); 47 | em.context_enter(); 48 | em.new_epoch(); 49 | em.new_epoch(); 50 | em.new_epoch(); 51 | LOG("context_quiesce"); 52 | em.context_quiesce(); 53 | em.new_epoch(); 54 | em.new_epoch(); 55 | em.new_epoch(); 56 | LOG("context_exit"); 57 | em.context_exit(); 58 | em.new_epoch(); 59 | em.new_epoch(); 60 | em.new_epoch(); 61 | DEFER(em.context_fini()); 62 | } 63 | -------------------------------------------------------------------------------- /masstree/kvstats.hh: -------------------------------------------------------------------------------- 1 | /* Masstree 2 | * Eddie Kohler, Yandong Mao, Robert Morris 3 | * Copyright (c) 2012-2013 President and Fellows of Harvard College 4 | * Copyright (c) 2012-2013 Massachusetts Institute of Technology 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, subject to the conditions 9 | * listed in the Masstree LICENSE file. These conditions include: you must 10 | * preserve this copyright notice, and you cannot mention the copyright 11 | * holders in advertising related to the Software without their permission. 12 | * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This 13 | * notice is a summary of the Masstree LICENSE file; the license in that file 14 | * is legally binding. 15 | */ 16 | #ifndef KVSTATS_HH 17 | #define KVSTATS_HH 1 18 | #include 19 | 20 | struct kvstats { 21 | double min, max, sum, sumsq; 22 | long count; 23 | kvstats() : min(-1), max(-1), sum(0), sumsq(0), count(0) {} 24 | void add(double x) { 25 | if (!count || x < min) min = x; 26 | if (max < x) max = x; 27 | sum += x; 28 | sumsq += x * x; 29 | count += 1; 30 | } 31 | typedef void (kvstats::*unspecified_bool_type)(double); 32 | operator unspecified_bool_type() const { return count ? &kvstats::add : 0; } 33 | void print_report(const char *name) const { 34 | if (count) 35 | printf( 36 | "%s: n %ld, total %.0f, average %.0f, min %.0f, max %.0f, stddev " 37 | "%.0f\n", 38 | name, count, sum, sum / count, min, max, 39 | sqrt((sumsq - sum * sum / count) / (count - 1))); 40 | } 41 | double avg() { 42 | if (count) 43 | return sum / count; 44 | else 45 | return 0; 46 | } 47 | }; 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/google/sparsetable: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // Header files have moved from the google directory to the sparsehash 31 | // directory. This forwarding file is provided only for backwards 32 | // compatibility. Use in all new code. 33 | 34 | #include 35 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/google/dense_hash_map: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // Header files have moved from the google directory to the sparsehash 31 | // directory. This forwarding file is provided only for backwards 32 | // compatibility. Use in all new code. 33 | 34 | #include 35 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/google/dense_hash_set: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // Header files have moved from the google directory to the sparsehash 31 | // directory. This forwarding file is provided only for backwards 32 | // compatibility. Use in all new code. 33 | 34 | #include 35 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/google/sparse_hash_map: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // Header files have moved from the google directory to the sparsehash 31 | // directory. This forwarding file is provided only for backwards 32 | // compatibility. Use in all new code. 33 | 34 | #include 35 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/google/sparse_hash_set: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // Header files have moved from the google directory to the sparsehash 31 | // directory. This forwarding file is provided only for backwards 32 | // compatibility. Use in all new code. 33 | 34 | #include 35 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/google/template_util.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // Header files have moved from the google directory to the sparsehash 31 | // directory. This forwarding file is provided only for backwards 32 | // compatibility. Use in all new code. 33 | 34 | #include 35 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/google/type_traits.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // Header files have moved from the google directory to the sparsehash 31 | // directory. This forwarding file is provided only for backwards 32 | // compatibility. Use in all new code. 33 | 34 | #include 35 | -------------------------------------------------------------------------------- /masstree/mtcounters.hh: -------------------------------------------------------------------------------- 1 | /* Masstree 2 | * Eddie Kohler, Yandong Mao, Robert Morris 3 | * Copyright (c) 2012-2013 President and Fellows of Harvard College 4 | * Copyright (c) 2012-2013 Massachusetts Institute of Technology 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, subject to the conditions 9 | * listed in the Masstree LICENSE file. These conditions include: you must 10 | * preserve this copyright notice, and you cannot mention the copyright 11 | * holders in advertising related to the Software without their permission. 12 | * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This 13 | * notice is a summary of the Masstree LICENSE file; the license in that file 14 | * is legally binding. 15 | */ 16 | #ifndef MTCOUNTERS_HH 17 | #define MTCOUNTERS_HH 1 18 | 19 | enum memtag { 20 | memtag_none = 0x0, 21 | memtag_value = 0x1, 22 | memtag_limbo = 0x5, 23 | memtag_masstree_leaf = 0x10, 24 | memtag_masstree_internode = 0x11, 25 | memtag_masstree_ksuffixes = 0x12, 26 | memtag_masstree_gc = 0x13 27 | }; 28 | 29 | enum threadcounter { 30 | // order is important among tc_alloc constants: 31 | tc_alloc, 32 | tc_alloc_value = tc_alloc, 33 | tc_alloc_other = tc_alloc + 1, 34 | // end tc_alloc constants 35 | tc_gc, 36 | tc_limbo_slots, 37 | tc_replay_create_delta, 38 | tc_replay_remove_delta, 39 | tc_root_retry, 40 | tc_internode_retry, 41 | tc_leaf_retry, 42 | tc_leaf_walk, 43 | // order is important among tc_stable constants: 44 | tc_stable, 45 | tc_stable_internode_insert = tc_stable + 0, 46 | tc_stable_internode_split = tc_stable + 1, 47 | tc_stable_leaf_insert = tc_stable + 2, 48 | tc_stable_leaf_split = tc_stable + 3, 49 | // end tc_stable constants 50 | tc_internode_lock, 51 | tc_leaf_lock, 52 | tc_max 53 | }; 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/google/sparsehash/densehashtable.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // Header files have moved from the google directory to the sparsehash 31 | // directory. This forwarding file is provided only for backwards 32 | // compatibility. Use in all new code. 33 | 34 | #include 35 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/google/sparsehash/sparsehashtable.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // Header files have moved from the google directory to the sparsehash 31 | // directory. This forwarding file is provided only for backwards 32 | // compatibility. Use in all new code. 33 | 34 | #include 35 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/google/sparsehash/hashtable-common.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // Header files have moved from the google directory to the sparsehash 31 | // directory. This forwarding file is provided only for backwards 32 | // compatibility. Use in all new code. 33 | 34 | #include 35 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/google/sparsehash/libc_allocator_with_realloc.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // Header files have moved from the google directory to the sparsehash 31 | // directory. This forwarding file is provided only for backwards 32 | // compatibility. Use in all new code. 33 | 34 | #include 35 | -------------------------------------------------------------------------------- /masstree/LICENSE: -------------------------------------------------------------------------------- 1 | This software is subject to the license below, which is referenced 2 | elsewhere using the phrase "the Masstree LICENSE file". This license 3 | is an MIT license, plus a clause (taken from the W3C license) 4 | requiring prior written permission to use our names in publicity. The 5 | AUTHORS file lists the people who have contributed to this software. 6 | 7 | =========================================================================== 8 | 9 | (c) 2011-2013 President and Fellows of Harvard College 10 | (c) 2010-2011 Regents of the University of California 11 | (c) 2010-2013 Massachusetts Institute of Technology 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a 14 | copy of this software and associated documentation files (the "Software"), 15 | to deal in the Software without restriction, including without limitation 16 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 | and/or sell copies of the Software, and to permit persons to whom the 18 | Software is furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in 21 | all copies or substantial portions of the Software. 22 | 23 | The name and trademarks of copyright holders may NOT be used in advertising 24 | or publicity pertaining to the Software without specific, written prior 25 | permission. Title to copyright in this Software and any associated 26 | documentation will at all times remain with copyright holders. 27 | 28 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 31 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 33 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 34 | DEALINGS IN THE SOFTWARE. 35 | -------------------------------------------------------------------------------- /dbcore/dlog-tx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "dlog-defs.h" 4 | #include "sm-oid.h" 5 | 6 | // Transaction-facing logging infrastructure that determines anything related to 7 | // manupulating the bytes recorded by dlog, such as log record format 8 | 9 | namespace ermia { 10 | 11 | namespace dlog { 12 | 13 | struct log_record { 14 | enum logrec_type { 15 | INSERT, 16 | UPDATE, 17 | }; 18 | 19 | logrec_type type; 20 | 21 | FID fid; 22 | OID oid; 23 | 24 | uint64_t csn; 25 | 26 | char data[0]; 27 | }; 28 | 29 | static uint32_t populate_log_record(log_record::logrec_type type, 30 | log_block *block, 31 | FID fid, OID oid, 32 | const char *after_image, 33 | const uint32_t size) { 34 | LOG_IF(FATAL, type != log_record::logrec_type::INSERT && type != log_record::logrec_type::UPDATE) 35 | << "Wrong log record type"; 36 | 37 | LOG_IF(FATAL, block->payload_size + size > block->capacity) << "No enough space in log block"; 38 | uint32_t off = block->payload_size; 39 | 40 | // Initialize the logrecord header 41 | log_record *logrec = (log_record *)(&block->payload[off]); 42 | 43 | // Copy contents 44 | logrec->type = type; 45 | logrec->fid = fid; 46 | logrec->oid = oid; 47 | logrec->csn = block->csn; 48 | memcpy(&logrec->data[0], after_image, size); 49 | 50 | // Account for the occupied space 51 | block->payload_size += align_up(size + sizeof(log_record)); 52 | return off; 53 | } 54 | 55 | inline static uint32_t log_insert(log_block *block, FID fid, OID oid, const char *image, const uint32_t size) { 56 | return populate_log_record(log_record::INSERT, block, fid, oid, image, size); 57 | } 58 | 59 | inline static uint32_t log_update(log_block *block, FID fid, OID oid, const char *image, const uint32_t size) { 60 | return populate_log_record(log_record::UPDATE, block, fid, oid, image, size); 61 | } 62 | 63 | 64 | } 65 | 66 | } // namespace ermia 67 | -------------------------------------------------------------------------------- /dbcore/tests/test-dynarray.cpp: -------------------------------------------------------------------------------- 1 | #include "dynarray.h" 2 | 3 | #include "sm-common.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | sigjmp_buf jbuf; 12 | 13 | extern "C" void handler(int, siginfo_t *si, void *) { 14 | ASSERT(si->si_code); 15 | siglongjmp(jbuf, si->si_code); 16 | } 17 | 18 | static void access(dynarray &d, size_t offset, bool should_fault) { 19 | fprintf(stderr, "About to make an access, should %sfault\n", 20 | should_fault ? "" : "not "); 21 | #ifdef __CYGWIN__ 22 | if (should_fault) { 23 | /* Our code enters an infinite loop on cygwin due to 24 | repeatedly retrying the same seg fault. The handler is 25 | never called. 26 | */ 27 | fprintf(stderr, 28 | " (Never mind. Skipping because Cygwin can't catch SIGSEGV.)\n"); 29 | return; 30 | } 31 | #endif 32 | if (int err = sigsetjmp(jbuf, 1)) { 33 | ASSERT(should_fault); 34 | ASSERT(err == SEGV_ACCERR); 35 | fprintf(stderr, " Faulted, as designed\n"); 36 | } else { 37 | // first time 38 | d[offset] = 0; 39 | ASSERT(not should_fault); 40 | fprintf(stderr, " No fault, as designed\n"); 41 | } 42 | } 43 | 44 | int main() { 45 | dynarray dummy; 46 | 47 | // test movable status 48 | dummy = dynarray(1024 * 1024, 1); 49 | 50 | // not copyable 51 | // dynarray d2(dummy); 52 | 53 | // swappable 54 | dynarray d; 55 | swap(dummy, d); 56 | 57 | struct sigaction sa; 58 | memset(&sa, 0, sizeof(sa)); 59 | sa.sa_sigaction = &handler; 60 | sa.sa_flags = SA_SIGINFO; 61 | sigemptyset(&sa.sa_mask); 62 | int err = sigaction(SIGSEGV, &sa, NULL); 63 | THROW_IF(err, os_error, errno, "Call to sigaction() failed"); 64 | 65 | access(d, d.size() - 1, false); 66 | access(d, d.size(), true); 67 | 68 | access(d, d.size() - 1, false); 69 | access(d, d.size(), true); 70 | 71 | d.resize(2 * d.size()); 72 | access(d, d.size() - 1, false); 73 | access(d, d.size(), true); 74 | 75 | d.truncate(d.size() / 2); 76 | access(d, d.size() - 1, false); 77 | access(d, d.size(), true); 78 | } 79 | -------------------------------------------------------------------------------- /masstree/timestamp.hh: -------------------------------------------------------------------------------- 1 | /* Masstree 2 | * Eddie Kohler, Yandong Mao, Robert Morris 3 | * Copyright (c) 2012-2013 President and Fellows of Harvard College 4 | * Copyright (c) 2012-2013 Massachusetts Institute of Technology 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, subject to the conditions 9 | * listed in the Masstree LICENSE file. These conditions include: you must 10 | * preserve this copyright notice, and you cannot mention the copyright 11 | * holders in advertising related to the Software without their permission. 12 | * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This 13 | * notice is a summary of the Masstree LICENSE file; the license in that file 14 | * is legally binding. 15 | */ 16 | #ifndef TIMESTAMP_HH 17 | #define TIMESTAMP_HH 18 | #include "compiler.hh" 19 | #include 20 | #include 21 | #include 22 | 23 | #if HAVE_INT64_T_IS_LONG_LONG 24 | #define PRIuKVTS "llu" 25 | #else 26 | #define PRIuKVTS "lu" 27 | #endif 28 | #define PRIKVTSPARTS "%lu.%06lu" 29 | 30 | #define KVTS_HIGHPART(t) ((unsigned long)((t) >> 32)) 31 | #define KVTS_LOWPART(t) ((unsigned long)(uint32_t)(t)) 32 | 33 | typedef uint64_t kvtimestamp_t; 34 | 35 | inline kvtimestamp_t timestamp() { 36 | struct timeval tv; 37 | gettimeofday(&tv, 0); 38 | return ((kvtimestamp_t)tv.tv_sec << 32) | (unsigned int)tv.tv_usec; 39 | } 40 | 41 | inline kvtimestamp_t timestamp_sub(kvtimestamp_t a, kvtimestamp_t b) { 42 | a -= b; 43 | if (KVTS_LOWPART(a) > 999999) a -= ((kvtimestamp_t)1 << 32) - 1000000; 44 | return a; 45 | } 46 | 47 | extern kvtimestamp_t initial_timestamp; 48 | 49 | inline double now() { 50 | struct timeval tv; 51 | gettimeofday(&tv, 0); 52 | return tv.tv_sec + tv.tv_usec / 1000000.0; 53 | } 54 | 55 | inline struct timespec &set_timespec(struct timespec &x, double y) { 56 | double ipart = floor(y); 57 | x.tv_sec = (long)ipart; 58 | x.tv_nsec = (long)((y - ipart) * 1e9); 59 | return x; 60 | } 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /dbcore/tests/test-cslist.cpp: -------------------------------------------------------------------------------- 1 | #include "cslist.h" 2 | 3 | #include 4 | #include 5 | 6 | #define LOG(msg, ...) fprintf(stderr, msg, ##__VA_ARGS__) 7 | struct node { 8 | node *next; 9 | int payload; 10 | }; 11 | typedef cslist mylist; 12 | int main() { 13 | mylist list; 14 | 15 | static size_t const nnodes = 7; 16 | node nodes[nnodes]; 17 | LOG("Pushing %zd nodes at the tail of the list, for popping in FIFO order\n", 18 | nnodes); 19 | for (size_t i = 0; i < nnodes; i++) { 20 | nodes[i].payload = i + 1; 21 | list.push_tail(nodes + i); 22 | } 23 | 24 | LOG("Popping the list until empty.\n\tExpected: 1 2 ... %zd\n\tFound: ", 25 | nnodes); 26 | while (node *n = list.pop_head()) { 27 | LOG(" %d", n->payload); 28 | } 29 | 30 | LOG("\n\nPushing %zd nodes at the head of the list, for popping in LIFO " 31 | "order\n", 32 | nnodes); 33 | for (size_t i = 0; i < nnodes; i++) { 34 | nodes[i].payload = i + 1; 35 | list.push_head(nodes + i); 36 | } 37 | 38 | LOG("Popping the list until empty.\n\tExpected: %zd ... 2 1\n\tFound: ", 39 | nnodes); 40 | while (node *n = list.pop_head()) { 41 | LOG(" %d", n->payload); 42 | } 43 | 44 | LOG("\n\nAlternating pushes to head and tail\n"); 45 | for (size_t i = 0; i < nnodes; i++) { 46 | nodes[i].payload = i + 1; 47 | if (i % 2) 48 | list.push_head(nodes + i); 49 | else 50 | list.push_tail(nodes + i); 51 | } 52 | 53 | LOG("Iterating over the list.\n\tExpected: %zd ... 2 1 3 ... %zd\n\tFound: " 54 | " ", 55 | nnodes - 1, nnodes); 56 | for (mylist::iterator it = list.begin(); it != list.end(); ++it) { 57 | LOG(" %d", it->payload); 58 | } 59 | 60 | LOG("\nPopping the list until empty.\n\tExpected: %zd ... 2 1 3 ... " 61 | "%zd\n\tFound: ", 62 | nnodes - 1, nnodes); 63 | while (node *n = list.pop_head()) { 64 | LOG(" %d", n->payload); 65 | } 66 | 67 | LOG("\n\nThe list should be empty now: %s\n", 68 | list.empty() ? "true" : "false"); 69 | LOG("Iterating over the empty list.\n\tExpected: \n\tFound: "); 70 | for (mylist::iterator it = list.begin(); it != list.end(); ++it) { 71 | LOG(" %d", it->payload); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /dbcore/sm-table.cpp: -------------------------------------------------------------------------------- 1 | #include "sm-table.h" 2 | #include "../engine.h" 3 | 4 | namespace ermia { 5 | 6 | std::unordered_map TableDescriptor::name_map; 7 | std::unordered_map TableDescriptor::fid_map; 8 | std::unordered_map TableDescriptor::index_map; 9 | 10 | TableDescriptor::TableDescriptor(std::string& name) 11 | : name(name), 12 | primary_index(nullptr), 13 | tuple_fid(0), 14 | tuple_array(nullptr), 15 | aux_fid_(0), 16 | aux_array_(nullptr) { 17 | } 18 | 19 | void TableDescriptor::Initialize() { 20 | tuple_fid = oidmgr->create_file(true); 21 | fid_map[tuple_fid] = this; 22 | tuple_array = oidmgr->get_array(tuple_fid); 23 | 24 | // Dedicated array for keys 25 | aux_fid_ = oidmgr->create_file(true); 26 | aux_array_ = oidmgr->get_array(aux_fid_); 27 | } 28 | 29 | void TableDescriptor::SetPrimaryIndex(OrderedIndex *index, const std::string &name) { 30 | ALWAYS_ASSERT(index); 31 | ALWAYS_ASSERT(!primary_index); 32 | primary_index = index; 33 | index_map[name] = index; 34 | index->SetArrays(true); 35 | } 36 | 37 | void TableDescriptor::AddSecondaryIndex(OrderedIndex *index, const std::string &name) { 38 | ALWAYS_ASSERT(index); 39 | sec_indexes.push_back(index); 40 | index_map[name] = index; 41 | index->SetArrays(false); 42 | } 43 | 44 | void TableDescriptor::Recover(FID tuple_fid, FID aux_fid, OID himark) { 45 | ALWAYS_ASSERT(tuple_fid == 0); 46 | tuple_fid = tuple_fid; 47 | aux_fid_ = aux_fid; 48 | 49 | // Both primary and secondary indexes point to the same descriptor 50 | if (!FidExists(tuple_fid)) { 51 | // Primary index 52 | oidmgr->recreate_file(tuple_fid); 53 | fid_map[tuple_fid] = this; 54 | } 55 | oidmgr->recreate_file(aux_fid_); 56 | fid_map[aux_fid_] = this; 57 | 58 | ALWAYS_ASSERT(oidmgr->file_exists(tuple_fid)); 59 | tuple_array = oidmgr->get_array(tuple_fid); 60 | ALWAYS_ASSERT(oidmgr->file_exists(aux_fid)); 61 | aux_array_ = oidmgr->get_array(aux_fid_); 62 | 63 | if (himark > 0) { 64 | tuple_array->ensure_size(tuple_array->alloc_size(himark)); 65 | aux_array_->ensure_size(aux_array_->alloc_size(himark)); 66 | oidmgr->recreate_allocator(tuple_fid, himark); 67 | } 68 | } 69 | } // namespace ermia 70 | -------------------------------------------------------------------------------- /masstree/compiler.cc: -------------------------------------------------------------------------------- 1 | /* Masstree 2 | * Eddie Kohler, Yandong Mao, Robert Morris 3 | * Copyright (c) 2012-2014 President and Fellows of Harvard College 4 | * Copyright (c) 2012-2014 Massachusetts Institute of Technology 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, subject to the conditions 9 | * listed in the Masstree LICENSE file. These conditions include: you must 10 | * preserve this copyright notice, and you cannot mention the copyright 11 | * holders in advertising related to the Software without their permission. 12 | * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This 13 | * notice is a summary of the Masstree LICENSE file; the license in that file 14 | * is legally binding. 15 | */ 16 | #include "compiler.hh" 17 | #include 18 | #include 19 | 20 | void fail_always_assert(const char* file, int line, 21 | const char* assertion, const char* message) { 22 | if (message) 23 | fprintf(stderr, "assertion \"%s\" [%s] failed: file \"%s\", line %d\n", 24 | message, assertion, file, line); 25 | else 26 | fprintf(stderr, "assertion \"%s\" failed: file \"%s\", line %d\n", 27 | assertion, file, line); 28 | abort(); 29 | } 30 | 31 | void fail_masstree_invariant(const char* file, int line, 32 | const char* assertion, const char* message) { 33 | if (message) 34 | fprintf(stderr, "invariant \"%s\" [%s] failed: file \"%s\", line %d\n", 35 | message, assertion, file, line); 36 | else 37 | fprintf(stderr, "invariant \"%s\" failed: file \"%s\", line %d\n", 38 | assertion, file, line); 39 | abort(); 40 | } 41 | 42 | void fail_masstree_precondition(const char* file, int line, 43 | const char* assertion, const char* message) { 44 | if (message) 45 | fprintf(stderr, "precondition \"%s\" [%s] failed: file \"%s\", line %d\n", 46 | message, assertion, file, line); 47 | else 48 | fprintf(stderr, "precondition \"%s\" failed: file \"%s\", line %d\n", 49 | assertion, file, line); 50 | abort(); 51 | } 52 | -------------------------------------------------------------------------------- /dbcore/burt-hash.h: -------------------------------------------------------------------------------- 1 | // -*- mode:c++ -*- 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | /* A family of fast, high-quality integer hashes due to Bob Jenkins 8 | [1]. He identifies 35 compact functions that achieve "full 9 | avalanche" status where toggling any bit of the input toggles 10 | 25-75% of output bits. These hashes are thus especially useful with 11 | power of two-sized hash tables. The integer versions require 12 | roughly 20 machine instructions and employ only shift, add/sub, and 13 | xor operations. The SIMD version is just as fast, but applies the 14 | hash function to four values simultaneously. 15 | 16 | [1] http://burtleburtle.net/bob/hash/integer.html 17 | */ 18 | struct burt_hash { 19 | typedef uint32_t(function)(uint32_t); 20 | 21 | static function *select_hash(uint32_t selector); 22 | 23 | burt_hash(uint32_t selector = 0) : fn(select_hash(selector)) {} 24 | 25 | uint32_t operator()(uint32_t x) const { return fn(x); } 26 | 27 | function *fn; 28 | }; 29 | 30 | struct burt_hash4 { 31 | typedef __v4si(function)(__v4si); 32 | 33 | static function *select_hash(uint32_t selector); 34 | 35 | burt_hash4(uint32_t selector = 0) : fn(select_hash(selector)) {} 36 | 37 | /* Emulate hashing one value with four different functions by 38 | hashing four different byte-permutations of the input. To avoid 39 | interacting badly with hash functions' habit of using 40 | bidirectional shifts (= rotations, if you squint), no two 41 | permutations are rotations of each other and no byte is placed 42 | in the same position twice. 43 | 44 | The first computed value is equivalent to the one computed by 45 | the integer function. 46 | 47 | The hope is that this will work well, given high-quality hash 48 | functions, but that has not been verified empirically. 49 | */ 50 | __v4si operator()(int32_t xi) const { 51 | __v4si x = {xi}; 52 | #ifdef __clang__ 53 | x = (__v4si)__builtin_shufflevector((__v16qi)x, (__v16qi)x, 0, 1, 2, 3, 3, 2, 0, 1, 2, 3, 1, 0, 1, 0, 3, 2); 54 | #else 55 | __v16qi k = {0, 1, 2, 3, 3, 2, 0, 1, 2, 3, 1, 0, 1, 0, 3, 2}; 56 | x = (__v4si)__builtin_shuffle((__v16qi)x, k); 57 | #endif 58 | return operator()(x); 59 | } 60 | 61 | __v4si operator()(__v4si x) const { return fn(x); } 62 | 63 | function *fn; 64 | }; 65 | -------------------------------------------------------------------------------- /masstree/str.cc: -------------------------------------------------------------------------------- 1 | /* Masstree 2 | * Eddie Kohler, Yandong Mao, Robert Morris 3 | * Copyright (c) 2012-2013 President and Fellows of Harvard College 4 | * Copyright (c) 2012-2013 Massachusetts Institute of Technology 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, subject to the conditions 9 | * listed in the Masstree LICENSE file. These conditions include: you must 10 | * preserve this copyright notice, and you cannot mention the copyright 11 | * holders in advertising related to the Software without their permission. 12 | * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This 13 | * notice is a summary of the Masstree LICENSE file; the license in that file 14 | * is legally binding. 15 | */ 16 | #include "str.hh" 17 | namespace lcdf { 18 | 19 | const Str Str::maxkey("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 20 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 21 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 22 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 23 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 24 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 25 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 26 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 27 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 28 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 29 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 30 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 31 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 32 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 33 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 34 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 35 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 36 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 37 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 38 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 39 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 40 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 41 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 42 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 43 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 44 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 45 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 46 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 47 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 48 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 49 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 50 | "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" 51 | "\xFF", 257); 52 | 53 | } // namespace lcdf 54 | -------------------------------------------------------------------------------- /dbcore/pcommit.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sm-config.h" 4 | #include "sm-thread.h" 5 | 6 | namespace ermia { 7 | 8 | namespace pcommit { 9 | 10 | static const uint64_t DIRTY_FLAG = uint64_t{1} << 63; 11 | extern uint64_t *_tls_durable_csn CACHE_ALIGNED; 12 | 13 | struct commit_queue { 14 | struct Entry { 15 | uint64_t csn; 16 | uint64_t start_time; 17 | Entry() : csn(0), start_time(0) {} 18 | }; 19 | Entry *queue; 20 | uint32_t start; 21 | uint32_t items; 22 | uint64_t total_latency_us; 23 | uint32_t length; 24 | mcs_lock lock; 25 | commit_queue() 26 | : start(0), items(0), total_latency_us(0), 27 | length(config::pcommit_queue_length) { 28 | queue = new Entry[length]; 29 | } 30 | ~commit_queue() { delete[] queue; } 31 | void push_back(uint64_t csn, uint64_t start_time, bool *flush, bool *insert); 32 | inline uint32_t size() { return items; } 33 | void extend(); 34 | }; 35 | 36 | class tls_committer { 37 | private: 38 | // Same as log id and thread id 39 | uint32_t id; 40 | commit_queue *_commit_queue CACHE_ALIGNED; 41 | 42 | public: 43 | tls_committer() {} 44 | ~tls_committer() {} 45 | 46 | inline uint32_t get_queue_size() { return _commit_queue->size(); } 47 | 48 | inline uint64_t get_latency() { return _commit_queue->total_latency_us; } 49 | 50 | // Mark committer as ongoing: some log blocks have not been durable 51 | inline void set_dirty_flag() { 52 | volatile_write(_tls_durable_csn[id], _tls_durable_csn[id] | DIRTY_FLAG); 53 | } 54 | 55 | // Get tls durable csn of this thread 56 | inline uint64_t get_tls_durable_csn() { 57 | return volatile_read(_tls_durable_csn[id]); 58 | } 59 | 60 | // Set tls durable csn of this thread 61 | inline void set_tls_durable_csn(uint64_t csn) { 62 | volatile_write(_tls_durable_csn[id], csn); 63 | } 64 | 65 | // Initialize a tls_committer object 66 | void initialize(uint32_t id); 67 | 68 | // Get the lowest tls durable csn among all threads 69 | uint64_t get_global_durable_csn(); 70 | 71 | // Enqueue commit queue of this thread 72 | inline void enqueue_committed_xct(uint64_t csn, bool *flush, bool *insert) { 73 | util::timer t; 74 | _commit_queue->push_back(csn, t.get_start(), flush, insert); 75 | } 76 | 77 | // Dequeue commit queue of this thread 78 | void dequeue_committed_xcts(); 79 | 80 | // Extend commit queue 81 | inline void extend_queue() { _commit_queue->extend(); } 82 | }; 83 | 84 | } // namespace pcommit 85 | 86 | } // namespace ermia 87 | -------------------------------------------------------------------------------- /dbcore/tests/test-window-buffer.cpp: -------------------------------------------------------------------------------- 1 | #include "window-buffer.h" 2 | 3 | #include "sm-defs.h" 4 | #include "w_rand.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | int main() { 11 | try { 12 | window_buffer buf(1 << 16); 13 | 14 | // test ability to fill and then empty 15 | size_t wstart = buf.write_begin(); 16 | char *wbuf = buf.write_buf(wstart, buf.available_to_write()); 17 | ASSERT(wbuf); 18 | for (size_t i = 0; i < buf.available_to_write(); i++) wbuf[i] = (char)i; 19 | 20 | buf.advance_writer(buf.write_end()); 21 | 22 | size_t rstart = buf.read_begin(); 23 | char const *rbuf = buf.read_buf(rstart, buf.available_to_read()); 24 | ASSERT(rbuf); 25 | for (size_t i = 0; i < buf.available_to_read(); i++) 26 | ASSERT(rbuf[i] == (char)i); 27 | 28 | buf.advance_reader(buf.read_end()); 29 | ASSERT(buf.available_to_write() == buf.window_size()); 30 | 31 | // now mix it up 32 | w_rand rng; 33 | size_t rbytes = buf.read_begin(); 34 | size_t wbytes = buf.write_begin(); 35 | std::deque reference; 36 | while (rbytes < 128 * 1024 * 1024) { 37 | if (rng.randn(2)) { 38 | // try to write some number of bytes 39 | size_t avail = buf.available_to_write(); 40 | if (not avail) continue; 41 | 42 | size_t nbytes = rng.randn(1, avail); 43 | char *wbuf = buf.write_buf(wbytes, nbytes); 44 | for (size_t i = 0; i < nbytes; i++) { 45 | char val = (char)rng.randn(256); 46 | reference.push_back(val); 47 | wbuf[i] = val; 48 | } 49 | wbytes += nbytes; 50 | buf.advance_writer(wbytes); 51 | } else { 52 | // try to read some bytes 53 | size_t avail = buf.available_to_read(); 54 | if (not avail) continue; 55 | 56 | size_t nbytes = rng.randn(1, avail); 57 | char const *rbuf = buf.read_buf(rbytes, nbytes); 58 | for (size_t i = 0; i < nbytes; i++) { 59 | char val = reference.front(); 60 | reference.pop_front(); 61 | ASSERT(rbuf[i] == val); 62 | } 63 | rbytes += nbytes; 64 | buf.advance_reader(rbytes); 65 | } 66 | } 67 | while (not reference.empty()) { 68 | char val = reference.front(); 69 | reference.pop_front(); 70 | ASSERT(val == *buf.read_buf(rbytes, 1)); 71 | rbytes++; 72 | buf.advance_reader(rbytes); 73 | } 74 | } catch (...) { 75 | fprintf(stderr, "Yikes!\n"); 76 | exit(-1); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /dbcore/size-encode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sm-defs.h" 4 | 5 | #include 6 | #include 7 | 8 | namespace ermia { 9 | 10 | /* 11 | Encode a non-negative size in 8 bits, using a format similar to 12 | floating point. As with a floating point representation, precision 13 | decreases as the magnitude increases. Also as with floating point, 14 | the encoding is order-preserving and codes can be compared directly. 15 | 16 | The encoding can represent values ranging from 0 (0x00) to 950272 17 | (0xfe); 0xff is reserved as NaN/invalid. To avoid clipping objects, 18 | the input is always rounded up to the next representable value 19 | before encoding it, with a maximum rounding error of 6.25%. 20 | 21 | Notably, the encoding represents nearly all k*2**i <= 928k exactly, 22 | for integer 0 < k < 32 and integer 0 <= i < 20. The only exceptions 23 | are: 25*2 (52), 27*2 (56), 29*2 (60), 31*2 (64), 29*4 (120), 31*4 24 | (128), 31*8 (256). It also represents several other "interesting" k 25 | exactly because those k often contain powers of two. For example 26 | 100*2**i = 25*2**(i+2) is always exact. 27 | 28 | Encoding is somewhat expensive (in no small part due to the 29 | requirement that we round up), but decoding is quite fast, requiring 30 | only 13 machine instructions (one branch) on x86_64 31 | */ 32 | uint8_t encode_size(size_t sz); 33 | 34 | /* Encode a size, aligning it to the power of two given (in bits) and 35 | rounding up to the nearest value that can be encoded exactly. 36 | 37 | Also, update [sz] to the aligned/rounded size. 38 | */ 39 | uint8_t encode_size_aligned(size_t &sz, 40 | size_t align_bits = DEFAULT_ALIGNMENT_BITS); 41 | 42 | /* Decode a size code returned by encode_size. 43 | 44 | Size codes are used to size allocations, and because they are 45 | approximate the allocation may be slightly larger than the object 46 | that occupies it. If this matters, the user (or the object) is 47 | responsible to track the object's true size in some other way. 48 | 49 | A value of zero decodes to zero, and INVALID_SIZE_CODE decodes to 50 | INVALID_SIZE; all other values decode to something between 1 and 51 | 950272. 52 | */ 53 | size_t decode_size(uint8_t code); 54 | 55 | static inline size_t decode_size_aligned( 56 | uint8_t code, size_t align_bits = DEFAULT_ALIGNMENT_BITS) { 57 | return decode_size(code) << align_bits; 58 | } 59 | 60 | static uint8_t const INVALID_SIZE_CODE = 0xff; 61 | static size_t const MAX_ENCODABLE_SIZE = 950272; 62 | static size_t const INVALID_SIZE = -1; 63 | 64 | } // namespace ermia 65 | -------------------------------------------------------------------------------- /dbcore/tests/test-size-encode.cpp: -------------------------------------------------------------------------------- 1 | #include "size-encode.h" 2 | 3 | // Intentional -- tester needs access to private state... 4 | #include "size-encode.cpp" 5 | 6 | #include "sm-defs.h" 7 | 8 | #include 9 | 10 | int main() { 11 | for (auto it : enumerate(_encode_size_tab)) { 12 | printf("%6d ", (int)it.second); 13 | if (not((it.first + 1) % 8)) printf("\n"); 14 | } 15 | 16 | printf("FYI: min/max representable values: %zd %zd\n", decode_size(0x00), 17 | decode_size(0xfe)); 18 | printf("Verify that code -> value -> code is consistent...\n"); 19 | for (int i = 0; i < 256; i++) { 20 | int x = decode_size(i); 21 | int j = encode_size(x); 22 | if (j != i) 23 | printf("\tOops! Non-reversible code: %02x -> %6d -> %02x\n", i, x, j); 24 | } 25 | 26 | printf("Verify decoding of the two edge cases...\n"); 27 | int val; 28 | if ((val = decode_size(0))) 29 | printf("\tOops! Zero code decodes to %d (instead of 0)\n", val); 30 | if ((val = decode_size(0xff)) != -1) 31 | printf("\tOops! Invalid code decodes to %d (instead of (-1)\n", val); 32 | 33 | printf("Verify encoding of the two edge cases...\n"); 34 | int code; 35 | if ((code = encode_size(0))) printf("\tOops! Zero encodes to %02x\n", code); 36 | if ((code = encode_size(decode_size(0xff))) != 0xff) 37 | printf("\tOops! Out of range value %zd encodes to %02x\n", 38 | decode_size(0xff), code); 39 | 40 | printf("Verify we always round sizes up...\n"); 41 | for (int i = EFIRST(0); i < (int)ELAST(15); i++) { 42 | uint8_t code = encode_size(i); 43 | int j = decode_size(code); 44 | if (j < i) printf("\tOops! %6d -> %02x -> %6d\n", i, code, j); 45 | } 46 | 47 | printf("Verify we don't round sizes up too far...\n"); 48 | for (int i = EFIRST(1); i < (int)ELAST(15); i++) { 49 | uint8_t code = encode_size(i); 50 | int j = decode_size(code - 1); 51 | if (j >= i) 52 | printf("\tOops! %6d -> %02x, but %02x -> %6d\n", i, code, code - 1, j); 53 | } 54 | 55 | printf("Verify that codes are ordered the same as their decoded values...\n"); 56 | for (int i = 1; i < 255; i++) { 57 | int a = decode_size(i - 1); 58 | int b = decode_size(i); 59 | if (a >= b) printf("\tOops! %02x < %02x -> %d >= %d\n", i - 1, i, a, b); 60 | } 61 | 62 | printf( 63 | "Check whether any multiples of powers of two are not represented " 64 | "exactly (expect 7)...\n"); 65 | for (size_t i = 2; decode_size(encode_size(i)) == i; i *= 2) { 66 | for (int j = 2; j < 32 and encode_size(j * i) != 0xff; j++) { 67 | if (decode_size(encode_size(j * i)) != j * i) 68 | printf("\t%d * %zd = %zd -> %zd\n", j, i, j * i, 69 | decode_size(encode_size(j * i))); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /masstree/GNUmakefile.in: -------------------------------------------------------------------------------- 1 | AR = ar 2 | CC = @CC@ 3 | CXX = @CXX@ 4 | CFLAGS = -g -W -Wall -O3 5 | DEPSDIR := .deps 6 | DEPCFLAGS = -MD -MF $(DEPSDIR)/$*.d -MP 7 | ifeq ($(strip $(MEMMGR)), ) 8 | MEMMGR = @MALLOC_LIBS@ 9 | endif 10 | ifneq ($(strip $(KEYSWAP)), ) 11 | CFLAGS += -DKEYSWAP 12 | endif 13 | ifneq ($(strip $(NOPREFETCH)), ) 14 | CFLAGS += -DNOPREFETCH 15 | endif 16 | ifneq ($(strip $(NOSUPERPAGE)), ) 17 | CFLAGS += -DNOSUPERPAGE 18 | endif 19 | LIBS = @LIBS@ -lpthread -lm 20 | LDFLAGS = @LDFLAGS@ 21 | 22 | all: test_atomics mtd mtclient mttest 23 | 24 | %.o: %.c config.h $(DEPSDIR)/stamp 25 | $(CXX) $(CFLAGS) $(DEPCFLAGS) -include config.h -c -o $@ $< 26 | 27 | %.o: %.cc config.h $(DEPSDIR)/stamp 28 | $(CXX) $(CFLAGS) $(DEPCFLAGS) -include config.h -c -o $@ $< 29 | 30 | %.S: %.o 31 | objdump -S $< > $@ 32 | 33 | libjson.a: json.o string.o straccum.o str.o msgpack.o \ 34 | clp.o kvrandom.o compiler.o kvthread.o 35 | @/bin/rm -f $@ 36 | $(AR) cru $@ $^ 37 | 38 | KVTREES = query_masstree.o \ 39 | value_string.o value_array.o value_versioned_array.o \ 40 | string_slice.o 41 | 42 | mtd: mtd.o log.o checkpoint.o file.o misc.o $(KVTREES) \ 43 | kvio.o libjson.a 44 | $(CXX) $(CFLAGS) -o $@ $^ $(MEMMGR) $(LDFLAGS) $(LIBS) 45 | 46 | mtclient: mtclient.o misc.o testrunner.o kvio.o libjson.a 47 | $(CXX) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) 48 | 49 | mttest: mttest.o misc.o checkpoint.o $(KVTREES) testrunner.o \ 50 | kvio.o libjson.a 51 | $(CXX) $(CFLAGS) -o $@ $^ $(MEMMGR) $(LDFLAGS) $(LIBS) 52 | 53 | test_string: test_string.o string.o straccum.o compiler.o 54 | $(CXX) $(CFLAGS) -o $@ $^ $(MEMMGR) $(LDFLAGS) $(LIBS) 55 | 56 | test_atomics: test_atomics.o string.o straccum.o kvrandom.o \ 57 | json.o compiler.o kvio.o 58 | $(CXX) $(CFLAGS) -o $@ $^ $(MEMMGR) $(LDFLAGS) $(LIBS) 59 | 60 | jsontest: jsontest.o string.o straccum.o json.o compiler.o 61 | $(CXX) $(CFLAGS) -o $@ $^ $(MEMMGR) $(LDFLAGS) $(LIBS) 62 | 63 | msgpacktest: msgpacktest.o string.o straccum.o json.o compiler.o msgpack.o 64 | $(CXX) $(CFLAGS) -o $@ $^ $(MEMMGR) $(LDFLAGS) $(LIBS) 65 | 66 | config.h: stamp-h 67 | 68 | GNUmakefile: GNUmakefile.in config.status 69 | CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status 70 | 71 | configure config.h.in: configure.ac 72 | autoreconf -i 73 | touch config.h.in 74 | 75 | config.status: configure 76 | ./configure @ac_configure_args@ 77 | 78 | $(DEPSDIR)/stamp: 79 | mkdir -p $(DEPSDIR) 80 | touch $@ 81 | 82 | stamp-h: config.h.in config.status 83 | CONFIG_FILES= $(SHELL) ./config.status 84 | echo > stamp-h 85 | 86 | clean: 87 | rm -f mtd mtclient mttest test_string test_atomics *.o libjson.a 88 | rm -rf .deps 89 | 90 | DEPFILES := $(wildcard $(DEPSDIR)/*.d) 91 | ifneq ($(DEPFILES),) 92 | include $(DEPFILES) 93 | endif 94 | 95 | .PHONY: clean all 96 | -------------------------------------------------------------------------------- /dbcore/sm-table.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "sm-common.h" 6 | #include "sm-oid.h" 7 | 8 | namespace ermia { 9 | 10 | class OrderedIndex; 11 | 12 | class TableDescriptor { 13 | public: 14 | // Map table name to descriptors, global, no CC 15 | static std::unordered_map name_map; 16 | 17 | // Map FID to descriptors, global, no CC 18 | static std::unordered_map fid_map; 19 | 20 | // Map index name to OrderedIndex (primary or secondary), global, no CC 21 | static std::unordered_map index_map; 22 | 23 | static inline OrderedIndex *GetIndex(const std::string &name) { 24 | return index_map[name]; 25 | } 26 | static inline bool NameExists(std::string name) { 27 | return name_map.find(name) != name_map.end(); 28 | } 29 | static inline bool FidExists(FID fid) { 30 | return fid_map.find(fid) != fid_map.end(); 31 | } 32 | static inline TableDescriptor* Get(std::string name) { 33 | return name_map[name]; 34 | } 35 | static inline TableDescriptor* Get(FID fid) { return fid_map[fid]; } 36 | static inline OrderedIndex* GetPrimaryIndex(const std::string& name) { 37 | return name_map[name]->GetPrimaryIndex(); 38 | } 39 | static inline OrderedIndex* GetPrimaryIndex(FID fid) { 40 | return fid_map[fid]->GetPrimaryIndex(); 41 | } 42 | static inline TableDescriptor* New(std::string name) { 43 | name_map[name] = new TableDescriptor(name); 44 | return name_map[name]; 45 | } 46 | static inline uint32_t NumTables() { return name_map.size(); } 47 | 48 | private: 49 | std::string name; 50 | OrderedIndex *primary_index; 51 | std::vector sec_indexes; 52 | 53 | FID tuple_fid; 54 | oid_array* tuple_array; 55 | 56 | // An auxiliary array: on primary this is the key array 57 | FID aux_fid_; 58 | oid_array* aux_array_; 59 | 60 | public: 61 | TableDescriptor(std::string& name); 62 | 63 | void Initialize(); 64 | void SetPrimaryIndex(OrderedIndex *index, const std::string &name); 65 | void AddSecondaryIndex(OrderedIndex *index, const std::string &name); 66 | void Recover(FID tuple_fid, FID key_fid, OID himark = 0); 67 | inline std::string& GetName() { return name; } 68 | inline OrderedIndex* GetPrimaryIndex() { return primary_index; } 69 | inline FID GetTupleFid() { return tuple_fid; } 70 | inline FID GetKeyFid() { 71 | return aux_fid_; 72 | } 73 | inline oid_array* GetKeyArray() { 74 | return aux_array_; 75 | } 76 | inline FID GetPersistentAddressFid() { 77 | return aux_fid_; 78 | } 79 | inline oid_array* GetPersistentAddressArray() { 80 | return aux_array_; 81 | } 82 | inline oid_array* GetTupleArray() { return tuple_array; } 83 | }; 84 | } // namespace ermia 85 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/windows/port.cc: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007, Google Inc. 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * Neither the name of Google Inc. nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * --- 31 | * Author: Craig Silverstein 32 | */ 33 | 34 | #include 35 | #ifndef WIN32 36 | # error You should only be including windows/port.cc in a windows environment! 37 | #endif 38 | 39 | #include "config.h" 40 | #include // for va_list, va_start, va_end 41 | #include "port.h" 42 | 43 | // Calls the windows _vsnprintf, but always NUL-terminate. 44 | int snprintf(char *str, size_t size, const char *format, ...) { 45 | if (size == 0) // not even room for a \0? 46 | return -1; // not what C99 says to do, but what windows does 47 | str[size-1] = '\0'; 48 | va_list ap; 49 | va_start(ap, format); 50 | const int r = _vsnprintf(str, size-1, format, ap); 51 | va_end(ap); 52 | return r; 53 | } 54 | 55 | std::string TmpFile(const char* basename) { 56 | char tmppath_buffer[1024]; 57 | int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer); 58 | if (tmppath_len <= 0 || tmppath_len >= sizeof(tmppath_buffer)) { 59 | return basename; // an error, so just bail on tmppath 60 | } 61 | snprintf(tmppath_buffer + tmppath_len, sizeof(tmppath_buffer) - tmppath_len, 62 | "\\%s", basename); 63 | return tmppath_buffer; 64 | } 65 | -------------------------------------------------------------------------------- /dbcore/pcommit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "pcommit.h" 4 | #include "sm-common.h" 5 | #include "../engine.h" 6 | #include "../macros.h" 7 | 8 | namespace ermia { 9 | 10 | namespace pcommit { 11 | 12 | // tls_committer-local durable CSNs - belongs to tls_committer 13 | // but stored here together 14 | uint64_t *_tls_durable_csn = 15 | (uint64_t *)malloc(sizeof(uint64_t) * config::MAX_THREADS); 16 | 17 | // Up to which CSN are we sure all transcations are durable 18 | std::atomic global_durable_csn(0); 19 | 20 | void commit_queue::push_back(uint64_t csn, uint64_t start_time, bool *flush, bool *insert) { 21 | CRITICAL_SECTION(cs, lock); 22 | // Signal a flush if the queue is over 80% full 23 | if (items >= length * 0.8) { 24 | *flush = true; 25 | } 26 | if (*insert && items < length) { 27 | uint32_t idx = (start + items) % length; 28 | volatile_write(queue[idx].csn, csn); 29 | volatile_write(queue[idx].start_time, start_time); 30 | volatile_write(items, items + 1); 31 | ASSERT(items == size()); 32 | *insert = false; 33 | } 34 | } 35 | 36 | void commit_queue::extend() { 37 | Entry *new_queue = new Entry[length * 2]; 38 | memcpy(new_queue, queue, sizeof(Entry) * length); 39 | length *= 2; 40 | delete[] queue; 41 | queue = new_queue; 42 | } 43 | 44 | void tls_committer::initialize(uint32_t id) { 45 | this->id = id; 46 | _commit_queue = new commit_queue(); 47 | } 48 | 49 | uint64_t tls_committer::get_global_durable_csn() { 50 | bool found = false; 51 | uint64_t min_dirty = std::numeric_limits::max(); 52 | uint64_t max_clean = 0; 53 | for (uint32_t i = 0; i < ermia::dlog::tlogs.size(); i++) { 54 | uint64_t csn = volatile_read(_tls_durable_csn[i]); 55 | if (csn) { 56 | if (csn & DIRTY_FLAG) { 57 | min_dirty = std::min(csn & ~DIRTY_FLAG, min_dirty); 58 | found = true; 59 | } else if (max_clean < csn) { 60 | max_clean = csn; 61 | } 62 | } 63 | } 64 | uint64_t ret = found ? min_dirty : max_clean; 65 | global_durable_csn.store(ret, std::memory_order_release); 66 | return ret; 67 | } 68 | 69 | void tls_committer::dequeue_committed_xcts() { 70 | uint64_t upto_csn = get_global_durable_csn(); 71 | util::timer t; 72 | uint64_t end_time = t.get_start(); 73 | CRITICAL_SECTION(cs, _commit_queue->lock); 74 | uint32_t n = volatile_read(_commit_queue->start); 75 | uint32_t size = _commit_queue->size(); 76 | uint32_t dequeue = 0; 77 | for (uint32_t j = 0; j < size; ++j) { 78 | uint32_t idx = (n + j) % _commit_queue->length; 79 | auto &entry = _commit_queue->queue[idx]; 80 | if (volatile_read(entry.csn) > upto_csn) { 81 | break; 82 | } 83 | _commit_queue->total_latency_us += end_time - entry.start_time; 84 | dequeue++; 85 | } 86 | _commit_queue->items -= dequeue; 87 | volatile_write(_commit_queue->start, (n + dequeue) % _commit_queue->length); 88 | } 89 | 90 | } // namespace pcommit 91 | 92 | } // namespace ermia 93 | -------------------------------------------------------------------------------- /dbcore/serial.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "sm-rc.h" 3 | #include "xid.h" 4 | #include "../macros.h" 5 | 6 | namespace ermia { 7 | 8 | #if defined(SSN) || defined(SSI) 9 | namespace TXN { 10 | 11 | void assign_reader_bitmap_entry(); 12 | void deassign_reader_bitmap_entry(); 13 | 14 | #ifdef SSN 15 | // returns true if serializable, false means exclusion window violation 16 | inline bool ssn_check_exclusion(xid_context* xc) { 17 | uint64_t ss = xc->sstamp.load(std::memory_order_acquire) & 18 | (~xid_context::sstamp_final_mark); 19 | #ifndef NDEBUG 20 | if (ss and xc->pstamp >= ss) printf("ssn exclusion failure\n"); 21 | #endif 22 | if (ss and xc->pstamp >= ss) { 23 | return false; 24 | } 25 | return true; 26 | } 27 | #endif 28 | 29 | struct readers_list { 30 | /* 31 | * A bitmap to account for readers in a tuple. One bit per reader thread. 32 | * Having four uint64_t enables us to support 256 concurrent readers at most. 33 | * 256 / 8 = 64 bytes = one cache line. 34 | */ 35 | struct bitmap_t { 36 | static const uint32_t CAPACITY = 37 | config::MAX_THREADS * config::MAX_COROS; // must be a multiple of 64 38 | static const uint32_t ARRAY_SIZE = CAPACITY / 64; 39 | uint64_t array[ARRAY_SIZE]; 40 | 41 | bitmap_t() { memset(array, '\0', sizeof(uint64_t) * ARRAY_SIZE); } 42 | 43 | bool is_empty(uint32_t coro_batch_idx, bool exclude_self); 44 | }; 45 | 46 | struct tls_bitmap_info { 47 | uint64_t entry; // the entry with my bit set 48 | uint32_t index; // which uint64_t in bitmap_t.array 49 | inline uint32_t xid_index() { 50 | ASSERT(entry); 51 | return index * 64 + __builtin_ctzll(entry); 52 | } 53 | }; 54 | 55 | bitmap_t bitmap; 56 | XID xids[bitmap_t::CAPACITY]; // one xid per bit position 57 | uint64_t last_read_mostly_clsns[bitmap_t::CAPACITY]; 58 | 59 | readers_list() { 60 | memset(xids, '\0', sizeof(XID) * bitmap_t::CAPACITY); 61 | memset(last_read_mostly_clsns, '\0', sizeof(LSN) * bitmap_t::CAPACITY); 62 | } 63 | }; 64 | 65 | uint64_t serial_get_last_read_mostly_cstamp(int xid_idx); 66 | void serial_stamp_last_committed_lsn(uint32_t coro_batch_idx, uint64_t lsn); 67 | void serial_deregister_reader_tx(uint32_t coro_batch_idx, readers_list::bitmap_t* tuple_readers_bitmap); 68 | void serial_register_reader_tx(uint32_t coro_batch_idx, readers_list::bitmap_t* tuple_readers_bitmap); 69 | void serial_register_tx(uint32_t coro_batch_idx, XID xid); 70 | void serial_deregister_tx(uint32_t coro_batch_idx, XID xid); 71 | 72 | extern readers_list rlist; 73 | 74 | struct readers_bitmap_iterator { 75 | readers_bitmap_iterator(readers_list::bitmap_t* bitmap) 76 | : array(bitmap->array), 77 | cur_entry_index(0), 78 | cur_entry(volatile_read(array[0])) {} 79 | 80 | int32_t next(uint32_t coro_batch_idx, bool skip_self = true); 81 | uint64_t* array; 82 | uint32_t cur_entry_index; 83 | uint64_t cur_entry; 84 | }; 85 | } // namespace TXN 86 | #endif 87 | } // namespace ermia 88 | -------------------------------------------------------------------------------- /dbcore/dlog-defs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace ermia { 4 | 5 | namespace dlog { 6 | 7 | // CSNs are 64-bit integers and are global; used for ordering transactions. 8 | // TLog LSNs (not to be confused with the "LSN" defined by sm-common.h and 9 | // encoded in a fat_ptr) are 64-bit integers and are local to a log; the pair uniquely identifies a log record. 11 | // 12 | // Note that out of the 64 bits, an LSN only uses 40 bits out of it, limiting 13 | // the max size of each tlog to 1TB. The rationale is to still be able to fit 14 | // the pair in 48 bits---which is the number of bits available in 15 | // a fat_ptr---so that we can encode a pair in a single fat_ptr. 16 | // Then log ids are 8-bit integers. This allows us to support up to 2^8=256 17 | // tlogs, i.e., 256 cores maximum. Should these limitations become a problem, we 18 | // could expand fat_ptrs to 16B. 19 | typedef uint64_t tlog_csn; 20 | typedef uint64_t tlog_lsn; 21 | static const tlog_csn INVALID_TLOG_CSN = ~uint64_t{0}; 22 | static const tlog_lsn INVALID_TLOG_LSN = ~uint64_t{0}; 23 | 24 | // A log block is the collection of log records generated by a transaction. A 25 | // transaction could have mutliple log blocks or a single one if the log block 26 | // is big enough to hold all the log records, this is further determined by the 27 | // log buffer and segment sizes - we cannot allow a log block to span two log 28 | // buffers or segments. 29 | // 30 | // Note that it is the "user's" job to populate a log block by laying out all 31 | // log records (log_record instances, one of another) in the [payload] part of 32 | // this structure, i.e., the log block here doesn't interpret the content of the 33 | // payload; it doesn't know about concepts such as FIDs and OIDs, which are up 34 | // to the user of dlog to use. Consequently, there is no "log record" concept 35 | // for dlog. This helps us keep a clean separation between dlog and its users. 36 | // 37 | // Upon commit dlog only deals with log blocks and copies log blocks in their 38 | // entirety to the log buffer from the transaction's scratch area (provided by 39 | // the caller). 40 | struct log_block { 41 | // CSN of the transaction who created this log block 42 | tlog_csn csn; 43 | 44 | // Size of this log block in bytes 45 | uint32_t payload_size; 46 | 47 | // Total capacity of this log block (could be greater than payload_size) 48 | uint32_t capacity; 49 | 50 | char padding[PAGE_SIZE- sizeof(csn) - sizeof(payload_size) - sizeof(capacity)]; 51 | 52 | // Actual data, which in turn is an array of log records; 53 | // must be the last element 54 | char payload[0]; 55 | 56 | log_block(uint32_t cap) : csn(INVALID_TLOG_CSN), payload_size(0), capacity(cap) {} 57 | ~log_block() {} 58 | 59 | // Size of this whole log block 60 | inline uint32_t total_size() { return sizeof(*this) + payload_size; } 61 | 62 | inline char *get_payload() { return &payload[0]; } 63 | }; 64 | } // namespace dlog 65 | 66 | } // namespace ermia 67 | -------------------------------------------------------------------------------- /third-party/foedus/zipfian_random.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015, Hewlett-Packard Development Company, LP. 3 | * This program is free software; you can redistribute it and/or modify it 4 | * under the terms of the GNU General Public License as published by the Free 5 | * Software Foundation; either version 2 of the License, or (at your option) 6 | * any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. You should have received a copy of the GNU General Public 12 | * License along with this program; if not, write to the Free Software 13 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 14 | * 15 | * HP designates this particular file as subject to the "Classpath" exception 16 | * as provided by HP in the LICENSE.txt file that accompanied this code. 17 | */ 18 | #ifndef FOEDUS_ASSORTED_ZIPFIAN_RANDOM_HPP_ 19 | #define FOEDUS_ASSORTED_ZIPFIAN_RANDOM_HPP_ 20 | 21 | #include 22 | 23 | #include 24 | 25 | #include "uniform_random.hpp" 26 | 27 | namespace foedus { 28 | namespace assorted { 29 | /** 30 | * @brief A simple zipfian generator based off of YCSB's Java implementation. 31 | * The major user is YCSB. 0 <= theta < 1, higher means more skewed. 32 | * Generates a random number between 0 and max_. 33 | * @ingroup ASSORTED 34 | */ 35 | class ZipfianRandom { 36 | private: 37 | double zeta(uint64_t n) { 38 | double sum = 0; 39 | for (uint64_t i = 0; i < n; i++) { 40 | sum += 1 / std::pow(i + 1, theta_); 41 | } 42 | return sum; 43 | } 44 | 45 | public: 46 | void init(uint64_t items, double theta, uint64_t urnd_seed) { 47 | max_ = items - 1; 48 | theta_ = theta; 49 | zetan_ = zeta(items); 50 | alpha_ = 1.0 / (1.0 - theta_); 51 | eta_ = (1 - std::pow(2.0 / items, 1 - theta_)) / (1 - zeta(2) / zetan_); 52 | urnd_.set_current_seed(urnd_seed); 53 | } 54 | 55 | ZipfianRandom(uint64_t items, double theta, uint64_t urnd_seed) { 56 | init(items, theta, urnd_seed); 57 | } 58 | 59 | ZipfianRandom() {} 60 | 61 | uint64_t next() { 62 | double u = urnd_.uniform_within(0, max_) / static_cast(max_); 63 | double uz = u * zetan_; 64 | if (uz < 1.0) { 65 | return 0; 66 | } 67 | 68 | if (uz < 1.0 + std::pow(0.5, theta_)) { 69 | return 1; 70 | } 71 | 72 | uint64_t ret = static_cast(max_ * std::pow(eta_ * u - eta_ + 1, alpha_)); 73 | return ret; 74 | } 75 | 76 | uint64_t get_current_seed() const { return urnd_.get_current_seed(); } 77 | void set_current_seed(uint64_t seed) { urnd_.set_current_seed(seed); } 78 | 79 | private: 80 | foedus::assorted::UniformRandom urnd_; 81 | uint64_t max_; 82 | uint64_t base_; 83 | double theta_; 84 | double zetan_; 85 | double alpha_; 86 | double eta_; 87 | }; 88 | 89 | } // namespace assorted 90 | } // namespace foedus 91 | 92 | #endif // FOEDUS_ASSORTED_ZIPFIAN_RANDOM_HPP_ 93 | 94 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/windows/port.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2007, Google Inc. 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are 6 | * met: 7 | * 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above 11 | * copyright notice, this list of conditions and the following disclaimer 12 | * in the documentation and/or other materials provided with the 13 | * distribution. 14 | * * Neither the name of Google Inc. nor the names of its 15 | * contributors may be used to endorse or promote products derived from 16 | * this software without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * --- 31 | * Author: Craig Silverstein 32 | * 33 | * These are some portability typedefs and defines to make it a bit 34 | * easier to compile this code -- in particular, unittests -- under VC++. 35 | * Other portability code is found in windows/sparsehash/internal/sparseconfig.h. 36 | * 37 | * Several of these are taken from glib: 38 | * http://developer.gnome.org/doc/API/glib/glib-windows-compatability-functions.html 39 | */ 40 | 41 | #ifndef SPARSEHASH_WINDOWS_PORT_H_ 42 | #define SPARSEHASH_WINDOWS_PORT_H_ 43 | 44 | #include 45 | #include "config.h" 46 | 47 | #ifdef WIN32 48 | 49 | #define WIN32_LEAN_AND_MEAN /* We always want minimal includes */ 50 | #include 51 | #include /* because we so often use open/close/etc */ 52 | #include 53 | 54 | // 4996: Yes, we're ok using the "unsafe" functions like _vsnprintf and fopen 55 | // 4127: We use "while (1)" sometimes: yes, we know it's a constant 56 | // 4181: type_traits_test is explicitly testing 'qualifier applied to reference' 57 | #pragma warning(disable:4996 4127 4181) 58 | 59 | 60 | // file I/O 61 | #define unlink _unlink 62 | #define strdup _strdup 63 | 64 | // We can't just use _snprintf as a drop-in replacement, because it 65 | // doesn't always NUL-terminate. :-( 66 | extern int snprintf(char *str, size_t size, const char *format, ...); 67 | 68 | extern std::string TmpFile(const char* basename); // used in hashtable_unittest 69 | 70 | #endif /* WIN32 */ 71 | 72 | #endif /* SPARSEHASH_WINDOWS_PORT_H_ */ 73 | -------------------------------------------------------------------------------- /varstr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "dbcore/sm-common.h" 4 | #include "util.h" 5 | 6 | #ifdef MASSTREE 7 | #include "masstree/string_slice.hh" 8 | #endif 9 | 10 | namespace ermia { 11 | struct varstr { 12 | friend std::ostream &operator<<(std::ostream &o, const varstr &k); 13 | 14 | public: 15 | inline varstr() : l(0), p(NULL) {} 16 | 17 | inline varstr(const uint8_t *p, uint32_t l) : l(l), p(p) {} 18 | inline varstr(const char *p, uint32_t l) : l(l), p((const uint8_t *)p) {} 19 | inline void copy_from(const uint8_t *s, uint32_t l) { 20 | copy_from((const char *)s, l); 21 | } 22 | inline void copy_from(const varstr *v) { copy_from(v->p, v->l); } 23 | 24 | inline void copy_from(const char *s, uint32_t ll) { 25 | if (ll) { 26 | memcpy((void *)p, s, ll); 27 | } 28 | l = ll; 29 | } 30 | 31 | inline bool operator==(const varstr &that) const { 32 | if (size() != that.size()) return false; 33 | return memcmp(data(), that.data(), size()) == 0; 34 | } 35 | 36 | inline bool operator!=(const varstr &that) const { return !operator==(that); } 37 | 38 | inline bool operator<(const varstr &that) const { 39 | int r = memcmp(data(), that.data(), std::min(size(), that.size())); 40 | return r < 0 || (r == 0 && size() < that.size()); 41 | } 42 | 43 | inline bool operator>=(const varstr &that) const { return !operator<(that); } 44 | 45 | inline bool operator<=(const varstr &that) const { 46 | int r = memcmp(data(), that.data(), std::min(size(), that.size())); 47 | return r < 0 || (r == 0 && size() <= that.size()); 48 | } 49 | 50 | inline bool operator>(const varstr &that) const { return !operator<=(that); } 51 | 52 | inline int compare(const varstr &that) const { 53 | return memcmp(data(), that.data(), std::min(size(), that.size())); 54 | } 55 | 56 | inline uint64_t slice() const { 57 | uint64_t ret = 0; 58 | uint8_t *rp = (uint8_t *)&ret; 59 | for (uint32_t i = 0; i < std::min(l, uint64_t(8)); i++) rp[i] = p[i]; 60 | return util::host_endian_trfm()(ret); 61 | } 62 | 63 | #ifdef MASSTREE 64 | inline uint64_t slice_at(int pos) const { 65 | return string_slice::make_comparable((const char *)p + pos, 66 | std::min(int(l - pos), 8)); 67 | } 68 | #endif 69 | 70 | inline varstr shift() const { 71 | ASSERT(l >= 8); 72 | return varstr(p + 8, l - 8); 73 | } 74 | 75 | inline varstr shift_many(uint32_t n) const { 76 | ASSERT(l >= 8 * n); 77 | return varstr(p + 8 * n, l - 8 * n); 78 | } 79 | 80 | inline uint32_t size() const { return l; } 81 | inline const uint8_t *data() const { return p; } 82 | inline uint8_t *data() { return (uint8_t *)(void*)p; } 83 | inline bool empty() const { return not size(); } 84 | 85 | #ifdef MASSTREE 86 | inline operator lcdf::Str() const { return lcdf::Str(p, l); } 87 | #endif 88 | 89 | inline void prefetch() { 90 | uint32_t i = 0; 91 | do { 92 | ::prefetch((const char *)(p + i)); 93 | i += CACHE_LINE_SIZE; 94 | } while (i < l); 95 | } 96 | 97 | uint64_t l; 98 | fat_ptr ptr; 99 | const uint8_t *p; // must be the last field 100 | }; 101 | } // namespace ermia 102 | -------------------------------------------------------------------------------- /dbcore/tests/test-sm-oid.cpp: -------------------------------------------------------------------------------- 1 | #include "sm-oid.h" 2 | 3 | #include "stopwatch.h" 4 | #include "w_rand.h" 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #define LOG(msg, ...) fprintf(stderr, msg "\n", ##__VA_ARGS__) 14 | 15 | sm_oid_mgr *om; 16 | bool done = false; 17 | 18 | static int const NTABLES = 100; 19 | FID tables[NTABLES]; 20 | 21 | extern "C" void *thread_main(void *arg) { 22 | int tnum = (uintptr_t)arg; 23 | 24 | uint64_t now = stopwatch_t::now(); 25 | uint32_t seed[] = { 26 | (uint32_t)(now >> 32), (uint32_t)now, (uint32_t)getpid(), (uint32_t)tnum, 27 | }; 28 | LOG("t%d seed: {0x%08x 0x%08x 0x%08x 0x%08x}", tnum, seed[0], seed[1], 29 | seed[2], seed[3]); 30 | 31 | w_rand rng(seed); 32 | 33 | /* Use a quadratic distribution of sorts so that some tables are 34 | heavy hitters 35 | */ 36 | int ntables = rng.randn(min(NTABLES, 10), NTABLES); 37 | int nsel = (ntables + 1) * (ntables + 1) - 1; 38 | std::vector oids[ntables]; 39 | 40 | while (not volatile_read(done)) { 41 | int idx = std::sqrt(rng.randn(1, nsel)) - 1; 42 | ASSERT(0 <= idx and idx < NTABLES); 43 | FID f = tables[idx]; 44 | 45 | // want to allocate slightly more often than we delete 46 | auto &olist = oids[idx]; 47 | int should_delete = (rng.randn(99) < 49) and not olist.empty(); 48 | if (should_delete) { 49 | int victim = rng.randn(olist.size()); 50 | OID v = olist[victim]; 51 | olist[victim] = olist.back(); 52 | olist.pop_back(); 53 | om->free_oid(f, v); 54 | } else { 55 | OID o = om->alloc_oid(f); 56 | om->oid_put(f, o, NULL_PTR); 57 | olist.push_back(o); 58 | } 59 | 60 | /* About 1% of the time, do a spot check for duplicates */ 61 | if (not rng.randn(100)) { 62 | std::set nodups(olist.begin(), olist.end()); 63 | ASSERT(nodups.size() == olist.size()); 64 | } 65 | } 66 | 67 | return 0; 68 | } 69 | 70 | int main() { 71 | /* No attempt at recovery for now (it's ont implemented yet). Just 72 | test out file creation/deletion and OID alloc/free 73 | */ 74 | om = sm_oid_mgr::create(NULL, NULL); 75 | 76 | { 77 | /* quick sanity test run */ 78 | LOG("creating a table"); 79 | auto f = om->create_file(true); 80 | LOG("Allocating OID from table %d", f); 81 | auto o = om->alloc_oid(f); 82 | LOG("Freeing OID %d", o); 83 | om->free_oid(f, o); 84 | LOG("Deleting table %d", f); 85 | om->destroy_file(f); 86 | } 87 | #if 0 88 | static int const NOIDS = 100; 89 | OID oids[NOIDS]; 90 | for (auto &o : oids) 91 | o = om->alloc_oid(f); 92 | #endif 93 | 94 | LOG("creating %d tables", NTABLES); 95 | for (auto &f : tables) f = om->create_file(true); 96 | 97 | static int const N = 4; 98 | pthread_t tids[N]; 99 | LOG("creating %d worker threads", N); 100 | for (int i = 0; i < N; i++) 101 | pthread_create(&tids[i], NULL, thread_main, (void *)(uintptr_t)i); 102 | 103 | LOG("sleeping for 10 seconds..."); 104 | sleep(10); 105 | done = true; 106 | 107 | LOG("joining worker threads"); 108 | for (auto tid : tids) pthread_join(tid, NULL); 109 | 110 | LOG("destroying tables"); 111 | for (auto f : tables) om->destroy_file(f); 112 | 113 | LOG("done!"); 114 | } 115 | -------------------------------------------------------------------------------- /str_arena.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "dbcore/sm-config.h" 4 | #include "dbcore/sm-common.h" 5 | #include "varstr.h" 6 | #include 7 | #include 8 | 9 | namespace ermia { 10 | class str_arena { 11 | public: 12 | static const size_t MinStrReserveLength = 2 * CACHELINE_SIZE; 13 | str_arena(uint32_t size_mb) : n(0) { 14 | // Make sure arena is only initialized after config is initialized so we have 15 | // a valid size 16 | ALWAYS_ASSERT(size_mb == config::arena_size_mb); 17 | 18 | // adler32 (log checksum) needs it aligned 19 | ALWAYS_ASSERT( 20 | not posix_memalign((void **)&str, DEFAULT_ALIGNMENT, size_mb * config::MB)); 21 | memset(str, '\0', config::arena_size_mb * config::MB); 22 | reset(); 23 | } 24 | 25 | // non-copyable/non-movable for the time being 26 | str_arena(str_arena &&) = delete; 27 | str_arena(const str_arena &) = delete; 28 | str_arena &operator=(const str_arena &) = delete; 29 | 30 | inline void reset() { 31 | ASSERT(n < config::arena_size_mb * config::MB); 32 | n = 0; 33 | } 34 | 35 | varstr *next(uint64_t size) { 36 | uint64_t off = n; 37 | n += align_up(size + sizeof(varstr)); 38 | ASSERT(n < config::arena_size_mb * config::MB); 39 | varstr *ret = new (str + off) varstr(str + off + sizeof(varstr), size); 40 | return ret; 41 | } 42 | 43 | // Return a raw char* starts aligned, with aligned up size 44 | char *next_raw_aligned(uint64_t alignment, uint64_t size) { 45 | uint64_t addr = align_up((uint64_t)str + n, (uint64_t)alignment); 46 | uint64_t off = addr - (uint64_t)str; 47 | ASSERT(off - n < alignment); 48 | n += ((off - n) + align_up(size, alignment)); 49 | ASSERT(n < config::arena_size_mb * config::MB); 50 | return (char *)addr; 51 | } 52 | 53 | // Same as next but wihtout varstr 54 | inline char *next_raw(uint64_t size) { 55 | uint64_t off = n; 56 | n += align_up(size); 57 | ASSERT(n < config::arena_size_mb * config::MB); 58 | return str + off; 59 | } 60 | 61 | // Assume the caller is the benchmark using str(Size(v)) 62 | inline void return_space(uint64_t size) { 63 | n -= (align_up(size + sizeof(varstr))); 64 | } 65 | 66 | varstr *atomic_next(uint64_t size) { 67 | uint64_t off = __atomic_fetch_add(&n, align_up(size + sizeof(varstr)), __ATOMIC_ACQ_REL); 68 | ASSERT(n < config::arena_size_mb * config::MB); 69 | varstr *ret = new (str + off) varstr(str + off + sizeof(varstr), size); 70 | return ret; 71 | } 72 | 73 | inline varstr *operator()(uint64_t size) { return next(size); } 74 | 75 | bool manages(const varstr *px) const { 76 | return (const char *)px >= str and 77 | (uint64_t) px->data() + px->size() <= (uint64_t)str + n; 78 | } 79 | 80 | private: 81 | char *str; 82 | size_t n; 83 | }; 84 | 85 | class scoped_str_arena { 86 | public: 87 | scoped_str_arena(str_arena *arena) : arena(arena) {} 88 | 89 | scoped_str_arena(str_arena &arena) : arena(&arena) {} 90 | 91 | scoped_str_arena(scoped_str_arena &&) = default; 92 | 93 | // non-copyable 94 | scoped_str_arena(const scoped_str_arena &) = delete; 95 | scoped_str_arena &operator=(const scoped_str_arena &) = delete; 96 | 97 | ~scoped_str_arena() { 98 | if (arena) 99 | arena->reset(); 100 | } 101 | 102 | ALWAYS_INLINE str_arena *get() { return arena; } 103 | 104 | private: 105 | str_arena *arena; 106 | }; 107 | } // namespace ermia 108 | -------------------------------------------------------------------------------- /engine_internal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "dbcore/sm-common.h" 4 | 5 | namespace ermia { 6 | 7 | // Base class for user-facing index implementations 8 | class OrderedIndex { 9 | friend class transaction; 10 | 11 | protected: 12 | TableDescriptor *table_descriptor; 13 | bool is_primary; 14 | FID self_fid; 15 | 16 | public: 17 | OrderedIndex(std::string table_name, bool is_primary); 18 | virtual ~OrderedIndex() {} 19 | inline TableDescriptor *GetTableDescriptor() { return table_descriptor; } 20 | inline bool IsPrimary() { return is_primary; } 21 | inline FID GetIndexFid() { return self_fid; } 22 | virtual void *GetTable() = 0; 23 | 24 | class ScanCallback { 25 | public: 26 | virtual ~ScanCallback() {} 27 | virtual bool Invoke(const char *keyp, size_t keylen, 28 | const varstr &value) = 0; 29 | }; 30 | 31 | // Get a record with a key of length keylen. The underlying DB does not manage 32 | // the memory associated with key. [rc] stores TRUE if found, FALSE otherwise. 33 | virtual PROMISE(void) GetRecord(transaction *t, rc_t &rc, const varstr &key, varstr &value, 34 | OID *out_oid = nullptr) = 0; 35 | 36 | // Return the OID that corresponds the given key 37 | virtual PROMISE(void) GetOID(const varstr &key, rc_t &rc, TXN::xid_context *xc, OID &out_oid, 38 | ConcurrentMasstree::versioned_node_t *out_sinfo = nullptr) = 0; 39 | 40 | // Update a database record with a key of length keylen, with mapping of length 41 | // valuelen. The underlying DB does not manage the memory pointed to by key or 42 | // value (a copy is made). 43 | // 44 | // If the does not already exist and config::upsert is set to true, insert. 45 | virtual PROMISE(rc_t) UpdateRecord(transaction *t, const varstr &key, varstr &value) = 0; 46 | 47 | // Insert a hot record with a key of length keylen. 48 | virtual PROMISE(rc_t) InsertRecord(transaction *t, const varstr &key, varstr &value, 49 | OID *out_oid = nullptr) = 0; 50 | 51 | // Insert a cold record with a key of length keylen. 52 | virtual PROMISE(rc_t) InsertColdRecord(transaction *t, const varstr &key, varstr &value, 53 | OID *out_oid = nullptr) = 0; 54 | 55 | // Map a key to an existing OID. Could be used for primary or secondary index. 56 | virtual PROMISE(bool) InsertOID(transaction *t, const varstr &key, OID oid) = 0; 57 | 58 | // Search [start_key, *end_key) if end_key is not null, otherwise 59 | // search [start_key, +infty) 60 | virtual PROMISE(rc_t) Scan(transaction *t, const varstr &start_key, 61 | const varstr *end_key, ScanCallback &callback) = 0; 62 | // Search (*end_key, start_key] if end_key is not null, otherwise 63 | // search (-infty, start_key] (starting at start_key and traversing 64 | // backwards) 65 | virtual PROMISE(rc_t) ReverseScan(transaction *t, const varstr &start_key, 66 | const varstr *end_key, ScanCallback &callback) = 0; 67 | 68 | // Default implementation calls put() with NULL (zero-length) value 69 | virtual PROMISE(rc_t) RemoveRecord(transaction *t, const varstr &key) = 0; 70 | 71 | virtual size_t Size() = 0; 72 | virtual std::map Clear() = 0; 73 | virtual void SetArrays(bool) = 0; 74 | 75 | /** 76 | * Insert key-oid pair to the underlying actual index structure. 77 | * 78 | * Returns false if the record already exists or there is potential phantom. 79 | */ 80 | virtual PROMISE(bool) InsertIfAbsent(transaction *t, const varstr &key, OID oid) = 0; 81 | }; 82 | 83 | } // namespace ermia 84 | -------------------------------------------------------------------------------- /masstree/hashcode.hh: -------------------------------------------------------------------------------- 1 | /* Masstree 2 | * Eddie Kohler, Yandong Mao, Robert Morris 3 | * Copyright (c) 2012-2013 President and Fellows of Harvard College 4 | * Copyright (c) 2012-2013 Massachusetts Institute of Technology 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, subject to the conditions 9 | * listed in the Masstree LICENSE file. These conditions include: you must 10 | * preserve this copyright notice, and you cannot mention the copyright 11 | * holders in advertising related to the Software without their permission. 12 | * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This 13 | * notice is a summary of the Masstree LICENSE file; the license in that file 14 | * is legally binding. 15 | */ 16 | #ifndef CLICK_HASHCODE_HH 17 | #define CLICK_HASHCODE_HH 18 | #include 19 | #include 20 | #include 21 | 22 | // Notes about the hashcode template: On GCC 4.3.0, "template <>" is required 23 | // on the specializations or they aren't used. Just plain overloaded 24 | // functions aren't used. The specializations must be e.g. "const char &", 25 | // not "char", or GCC complains about a specialization not matching the 26 | // general template. The main template takes a const reference for two 27 | // reasons. First, providing both "hashcode_t hashcode(T)" and "hashcode_t 28 | // hashcode(const T&)" leads to ambiguity errors. Second, providing only 29 | // "hashcode_t hashcode(T)" is slower by looks like 8% when T is a String, 30 | // because of copy constructors; for types with more expensive non-default 31 | // copy constructors this would probably be worse. 32 | 33 | typedef size_t hashcode_t; ///< Typical type for a hashcode() value. 34 | 35 | template 36 | inline hashcode_t hashcode(T const &x) { 37 | return x.hashcode(); 38 | } 39 | 40 | template <> 41 | inline hashcode_t hashcode(char const &x) { 42 | return x; 43 | } 44 | 45 | template <> 46 | inline hashcode_t hashcode(signed char const &x) { 47 | return x; 48 | } 49 | 50 | template <> 51 | inline hashcode_t hashcode(unsigned char const &x) { 52 | return x; 53 | } 54 | 55 | template <> 56 | inline hashcode_t hashcode(short const &x) { 57 | return x; 58 | } 59 | 60 | template <> 61 | inline hashcode_t hashcode(unsigned short const &x) { 62 | return x; 63 | } 64 | 65 | template <> 66 | inline hashcode_t hashcode(int const &x) { 67 | return x; 68 | } 69 | 70 | template <> 71 | inline hashcode_t hashcode(unsigned const &x) { 72 | return x; 73 | } 74 | 75 | template <> 76 | inline hashcode_t hashcode(long const &x) { 77 | return x; 78 | } 79 | 80 | template <> 81 | inline hashcode_t hashcode(unsigned long const &x) { 82 | return x; 83 | } 84 | 85 | template <> 86 | inline hashcode_t hashcode(long long const &x) { 87 | return (x >> 32) ^ x; 88 | } 89 | 90 | template <> 91 | inline hashcode_t hashcode(unsigned long long const &x) { 92 | return (x >> 32) ^ x; 93 | } 94 | 95 | #if (defined(HAVE_INT64_TYPES) && HAVE_INT64_TYPES)&& !HAVE_INT64_IS_LONG && !HAVE_INT64_IS_LONG_LONG 96 | template <> 97 | inline hashcode_t hashcode(int64_t const &x) { 98 | return (x >> 32) ^ x; 99 | } 100 | 101 | template <> 102 | inline hashcode_t hashcode(uint64_t const &x) { 103 | return (x >> 32) ^ x; 104 | } 105 | #endif 106 | 107 | template 108 | inline hashcode_t hashcode(T *const &x) { 109 | return reinterpret_cast(x) >> 3; 110 | } 111 | 112 | template 113 | inline typename T::key_const_reference hashkey(const T &x) { 114 | return x.hashkey(); 115 | } 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /third-party/foedus/uniform_random.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015, Hewlett-Packard Development Company, LP. 3 | * This program is free software; you can redistribute it and/or modify it 4 | * under the terms of the GNU General Public License as published by the Free 5 | * Software Foundation; either version 2 of the License, or (at your option) 6 | * any later version. 7 | * 8 | * This program is distributed in the hope that it will be useful, but WITHOUT 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 | * more details. You should have received a copy of the GNU General Public 12 | * License along with this program; if not, write to the Free Software 13 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 14 | * 15 | * HP designates this particular file as subject to the "Classpath" exception 16 | * as provided by HP in the LICENSE.txt file that accompanied this code. 17 | */ 18 | #ifndef FOEDUS_ASSORTED_UNIFORM_RANDOM_HPP_ 19 | #define FOEDUS_ASSORTED_UNIFORM_RANDOM_HPP_ 20 | 21 | #include 22 | #include "../../macros.h" 23 | 24 | namespace foedus { 25 | namespace assorted { 26 | /** 27 | * @brief A very simple and deterministic random generator that is more aligned with standard 28 | * benchmark such as TPC-C. 29 | * @ingroup ASSORTED 30 | * @details 31 | * Actually this is exactly from TPC-C spec. 32 | */ 33 | class UniformRandom { 34 | public: 35 | UniformRandom() : seed_(0) {} 36 | explicit UniformRandom(uint64_t seed) : seed_(seed) {} 37 | 38 | /** 39 | * In TPCC terminology, from=x, to=y. 40 | * NOTE both from and to are _inclusive_. 41 | */ 42 | uint32_t uniform_within(uint32_t from, uint32_t to) { 43 | ALWAYS_ASSERT(from <= to); 44 | if (from == to) { 45 | return from; 46 | } 47 | return from + (next_uint32() % (to - from + 1)); 48 | } 49 | /** 50 | * Same as uniform_within() except it avoids the "except" value. 51 | * Make sure from!=to. 52 | */ 53 | uint32_t uniform_within_except(uint32_t from, uint32_t to, uint32_t except) { 54 | while (true) { 55 | uint32_t val = uniform_within(from, to); 56 | if (val != except) { 57 | return val; 58 | } 59 | } 60 | } 61 | 62 | /** 63 | * @brief Non-Uniform random (NURand) in TPCC spec (see Sec 2.1.6). 64 | * @details 65 | * In TPCC terminology, from=x, to=y. 66 | * NURand(A, x, y) = (((random(0, A) | random(x, y)) + C) % (y - x + 1)) + x 67 | */ 68 | uint32_t non_uniform_within(uint32_t A, uint32_t from, uint32_t to) { 69 | uint32_t C = get_c(A); 70 | return (((uniform_within(0, A) | uniform_within(from, to)) + C) % (to - from + 1)) + from; 71 | } 72 | 73 | uint64_t get_current_seed() const { 74 | return seed_; 75 | } 76 | void set_current_seed(uint64_t seed) { 77 | seed_ = seed; 78 | } 79 | uint64_t next_uint64() { 80 | return (static_cast(next_uint32()) << 32) | next_uint32(); 81 | } 82 | uint32_t next_uint32() { 83 | seed_ = seed_ * 0xD04C3175 + 0x53DA9022; 84 | return (seed_ >> 32) ^ (seed_ & 0xFFFFFFFF); 85 | } 86 | 87 | private: 88 | uint64_t seed_; 89 | 90 | /** 91 | * C is a run-time constant randomly chosen within [0 .. A] that can be 92 | * varied without altering performance. The same C value, per field 93 | * (C_LAST, C_ID, and OL_I_ID), must be used by all emulated terminals. 94 | * constexpr, but let's not bother C++11. 95 | */ 96 | uint32_t get_c(uint32_t A) const { 97 | // yes, I'm lazy. but this satisfies the spec. 98 | const uint64_t kCSeed = 0x734b00c6d7d3bbdaULL; 99 | return kCSeed % (A + 1); 100 | } 101 | }; 102 | 103 | } // namespace assorted 104 | } // namespace foedus 105 | 106 | #endif // FOEDUS_ASSORTED_UNIFORM_RANDOM_HPP_ 107 | 108 | -------------------------------------------------------------------------------- /dbcore/stub-impl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sm-defs.h" 4 | 5 | #include 6 | #include 7 | 8 | namespace ermia { 9 | 10 | /* This file provides support for a "stub-impl" idiom, where a "stub" 11 | class contains all world-facing members of an object, and an "impl" 12 | class contains all private/internal state. This idiom combines the 13 | concept of an interface (abstract base class) with the "pimple" 14 | idiom, but avoids the drawbacks of both: There are no extra 15 | pointers to chase, and method calls have no overhead vs. a normal 16 | class (this is true even when an "interface" method calls an "impl" 17 | method). Internally, this desirable outcome is achieved by 18 | arranging for the impl object to inherit from the stub, and then 19 | upcasting, but this detail is transparent to the stub's user. 20 | 21 | The one drawback is that stub-impl objects cannot be allocated 22 | directly by the user, but must be created and destroyed by factory 23 | methods. We can prevent the user from instantiating stubs directly, 24 | and we can also prevent the developer from creating multiple 25 | implementations (this is *not* a mechanism to support 26 | polymorphism). 27 | 28 | // in .h ////////////////////////////// 29 | 30 | // the "stub" is world-visible 31 | struct foo { 32 | // note lack of data members 33 | 34 | // factory methods instead of constructor/destructor 35 | static 36 | foo *make(); 37 | 38 | void destroy(); 39 | 40 | // public method 41 | void bar(); 42 | 43 | protected: 44 | // prevent users from allocating the stub directly 45 | foo() { } 46 | ~foo() { } 47 | }; 48 | /////////////////////////////////////// 49 | 50 | // in .cpp //////////////////////////// 51 | 52 | // derive the "impl" class from stub 53 | struct foo_impl : foo { 54 | // a private method 55 | void baz(); 56 | }; 57 | 58 | // must DEF_IMPL *after* defining the "impl" class 59 | DEF_IMPL(foo); 60 | 61 | // define factory methods for stub 62 | foo *foo::make() { 63 | return new foo_impl; 64 | } 65 | void foo::destroy() { 66 | delete get_impl(this); 67 | } 68 | 69 | // define "stub" functions 70 | void foo::bar() { 71 | get_impl(this)->baz(); 72 | } 73 | 74 | ////////////////////////////////////// 75 | */ 76 | 77 | /* Invoke this macro after defining the impl class. 78 | 79 | The impl class must derive from the stub class. 80 | 81 | NOTE: N2965 proposes a std::direct_bases trait which would be 82 | perfect for this, but gcc is the only compiler that implements it 83 | and the proposal appears to be dead in the water. Avoiding it. 84 | */ 85 | #define DEF_IMPL(tp) DEF_IMPL2(tp, tp##_impl) 86 | 87 | #define DEF_IMPL2(tp, impl) \ 88 | static_assert(std::is_base_of::value, \ 89 | #impl " is not derived from " #tp); \ 90 | template <> \ 91 | struct _impl_of { \ 92 | typedef impl type; \ 93 | } 94 | 95 | template 96 | struct _impl_of { 97 | typedef T type; 98 | }; 99 | 100 | /* Given a pointer to T (a stub), return a pointer to T's 101 | implementation. The default is to return a pointer to T. If the 102 | user has declared a stub-impl relationship, return a pointer to the 103 | impl instead. This ensures that only one implementation exists. 104 | */ 105 | template 106 | typename _impl_of::type *get_impl(T *ptr) { 107 | return (typename _impl_of::type *)ptr; 108 | } 109 | template 110 | typename _impl_of::type const *get_impl(T const *ptr) { 111 | return (typename _impl_of::type const *)ptr; 112 | } 113 | 114 | } // namespace ermia 115 | -------------------------------------------------------------------------------- /masstree/masstree_get.hh: -------------------------------------------------------------------------------- 1 | /* Masstree 2 | * Eddie Kohler, Yandong Mao, Robert Morris 3 | * Copyright (c) 2012-2014 President and Fellows of Harvard College 4 | * Copyright (c) 2012-2014 Massachusetts Institute of Technology 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, subject to the conditions 9 | * listed in the Masstree LICENSE file. These conditions include: you must 10 | * preserve this copyright notice, and you cannot mention the copyright 11 | * holders in advertising related to the Software without their permission. 12 | * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This 13 | * notice is a summary of the Masstree LICENSE file; the license in that file 14 | * is legally binding. 15 | */ 16 | #ifndef MASSTREE_GET_HH 17 | #define MASSTREE_GET_HH 1 18 | #include "masstree_tcursor.hh" 19 | #include "masstree_key.hh" 20 | #include "../dbcore/sm-coroutine.h" 21 | #include "../uintr.h" 22 | namespace Masstree { 23 | 24 | template 25 | PROMISE(bool) unlocked_tcursor

::find_unlocked(contextinfo& ti) { 26 | int match; 27 | key_indexed_position kx; 28 | node_base

* root = const_cast*>(root_); 29 | 30 | retry: 31 | n_ = AWAIT root->reach_leaf(ka_, v_, ti); 32 | 33 | forward: 34 | if (v_.deleted()) goto retry; 35 | 36 | n_->prefetch(); 37 | SUSPEND; 38 | perm_ = n_->permutation(); 39 | kx = leaf

::bound_type::lower(ka_, *this); 40 | if (kx.p >= 0) { 41 | lv_ = n_->lv_[kx.p]; 42 | lv_.prefetch(n_->keylenx_[kx.p]); 43 | SUSPEND; 44 | match = n_->ksuf_matches(kx.p, ka_); 45 | } else 46 | match = 0; 47 | if (n_->has_changed(v_)) { 48 | n_ = n_->advance_to_key(ka_, v_, ti); 49 | goto forward; 50 | } 51 | 52 | if (match < 0) { 53 | ka_.shift_by(-match); 54 | root = lv_.layer(); 55 | goto retry; 56 | } else 57 | RETURN match; 58 | } 59 | 60 | template 61 | inline PROMISE(bool) basic_table

::get( 62 | Str key, value_type& value, 63 | contextinfo& ti) const { 64 | unlocked_tcursor

lp(*this, key); 65 | bool found = AWAIT lp.find_unlocked(ti); 66 | if (found) value = lp.value(); 67 | RETURN found; 68 | } 69 | 70 | template 71 | PROMISE(bool) tcursor

::find_locked(contextinfo& ti) { 72 | pcontext::lock(); 73 | node_base

* root = const_cast*>(root_); 74 | nodeversion_type v; 75 | permuter_type perm; 76 | 77 | retry: 78 | n_ = AWAIT root->reach_leaf(ka_, v, ti); 79 | 80 | forward: 81 | if (v.deleted()) goto retry; 82 | 83 | n_->prefetch(); 84 | perm = n_->permutation(); 85 | fence(); 86 | kx_ = leaf

::bound_type::lower(ka_, *n_); 87 | if (kx_.p >= 0) { 88 | leafvalue

lv = n_->lv_[kx_.p]; 89 | lv.prefetch(n_->keylenx_[kx_.p]); 90 | state_ = n_->ksuf_matches(kx_.p, ka_); 91 | if (state_ < 0 && !n_->has_changed(v) && !lv.layer()->has_split()) { 92 | ka_.shift_by(-state_); 93 | root = lv.layer(); 94 | goto retry; 95 | } 96 | } else { 97 | state_ = 0; 98 | } 99 | n_->lock(v, ti.lock_fence(tc_leaf_lock)); 100 | if (n_->has_changed(v) || n_->permutation() != perm) { 101 | n_->unlock(); 102 | n_ = n_->advance_to_key(ka_, v, ti); 103 | goto forward; 104 | } else if (unlikely(state_ < 0)) { 105 | ka_.shift_by(-state_); 106 | n_->lv_[kx_.p] = root = n_->lv_[kx_.p].layer()->unsplit_ancestor(); 107 | n_->unlock(); 108 | goto retry; 109 | } else if (unlikely(n_->deleted_layer())) { 110 | ka_.unshift_all(); 111 | root = const_cast*>(root_); 112 | goto retry; 113 | } 114 | pcontext::unlock(); 115 | RETURN state_; 116 | } 117 | 118 | } // namespace Masstree 119 | #endif 120 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/config.h: -------------------------------------------------------------------------------- 1 | /* src/config.h. Generated from config.h.in by configure. */ 2 | /* src/config.h.in. Generated from configure.ac by autoheader. */ 3 | 4 | /* Namespace for Google classes */ 5 | #define GOOGLE_NAMESPACE ::google 6 | 7 | /* the location of the header defining hash functions */ 8 | #define HASH_FUN_H 9 | 10 | /* the location of or */ 11 | #define HASH_MAP_H 12 | 13 | /* the namespace of the hash<> function */ 14 | #define HASH_NAMESPACE std::tr1 15 | 16 | /* the location of or */ 17 | #define HASH_SET_H 18 | 19 | /* Define to 1 if you have the header file. */ 20 | #define HAVE_GOOGLE_MALLOC_EXTENSION_H 1 21 | 22 | /* define if the compiler has hash_map */ 23 | #define HAVE_HASH_MAP 1 24 | 25 | /* define if the compiler has hash_set */ 26 | #define HAVE_HASH_SET 1 27 | 28 | /* Define to 1 if you have the header file. */ 29 | #define HAVE_INTTYPES_H 1 30 | 31 | /* Define to 1 if the system has the type `long long'. */ 32 | #define HAVE_LONG_LONG 1 33 | 34 | /* Define to 1 if you have the `memcpy' function. */ 35 | #define HAVE_MEMCPY 1 36 | 37 | /* Define to 1 if you have the `memmove' function. */ 38 | #define HAVE_MEMMOVE 1 39 | 40 | /* Define to 1 if you have the header file. */ 41 | #define HAVE_MEMORY_H 1 42 | 43 | /* define if the compiler implements namespaces */ 44 | #define HAVE_NAMESPACES 1 45 | 46 | /* Define if you have POSIX threads libraries and header files. */ 47 | #define HAVE_PTHREAD 1 48 | 49 | /* Define to 1 if you have the header file. */ 50 | #define HAVE_STDINT_H 1 51 | 52 | /* Define to 1 if you have the header file. */ 53 | #define HAVE_STDLIB_H 1 54 | 55 | /* Define to 1 if you have the header file. */ 56 | #define HAVE_STRINGS_H 1 57 | 58 | /* Define to 1 if you have the header file. */ 59 | #define HAVE_STRING_H 1 60 | 61 | /* Define to 1 if you have the header file. */ 62 | #define HAVE_SYS_RESOURCE_H 1 63 | 64 | /* Define to 1 if you have the header file. */ 65 | #define HAVE_SYS_STAT_H 1 66 | 67 | /* Define to 1 if you have the header file. */ 68 | #define HAVE_SYS_TIME_H 1 69 | 70 | /* Define to 1 if you have the header file. */ 71 | #define HAVE_SYS_TYPES_H 1 72 | 73 | /* Define to 1 if you have the header file. */ 74 | #define HAVE_SYS_UTSNAME_H 1 75 | 76 | /* Define to 1 if the system has the type `uint16_t'. */ 77 | #define HAVE_UINT16_T 1 78 | 79 | /* Define to 1 if you have the header file. */ 80 | #define HAVE_UNISTD_H 1 81 | 82 | /* define if the compiler supports unordered_{map,set} */ 83 | #define HAVE_UNORDERED_MAP 1 84 | 85 | /* Define to 1 if the system has the type `u_int16_t'. */ 86 | #define HAVE_U_INT16_T 1 87 | 88 | /* Define to 1 if the system has the type `__uint16'. */ 89 | /* #undef HAVE___UINT16 */ 90 | 91 | /* Define to the full name of this package. */ 92 | #define PACKAGE_NAME "sparsehash" 93 | 94 | /* Define to the full name and version of this package. */ 95 | #define PACKAGE_STRING "sparsehash 2.0.2" 96 | 97 | /* Define to the one symbol short name of this package. */ 98 | #define PACKAGE_TARNAME "sparsehash" 99 | 100 | /* Define to the home page for this package. */ 101 | #define PACKAGE_URL "" 102 | 103 | /* Define to necessary symbol if this constant uses a non-standard name on 104 | your system. */ 105 | /* #undef PTHREAD_CREATE_JOINABLE */ 106 | 107 | /* The system-provided hash function including the namespace. */ 108 | #define SPARSEHASH_HASH HASH_NAMESPACE::hash 109 | 110 | /* The system-provided hash function, in namespace HASH_NAMESPACE. */ 111 | #define SPARSEHASH_HASH_NO_NAMESPACE hash 112 | 113 | /* Define to 1 if you have the ANSI C header files. */ 114 | #define STDC_HEADERS 1 115 | 116 | /* Stops putting the code inside the Google namespace */ 117 | #define _END_GOOGLE_NAMESPACE_ } 118 | 119 | /* Puts following code inside the Google namespace */ 120 | #define _START_GOOGLE_NAMESPACE_ namespace google { 121 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/config.h.in: -------------------------------------------------------------------------------- 1 | /* src/config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Namespace for Google classes */ 4 | #undef GOOGLE_NAMESPACE 5 | 6 | /* the location of the header defining hash functions */ 7 | #undef HASH_FUN_H 8 | 9 | /* the location of or */ 10 | #undef HASH_MAP_H 11 | 12 | /* the namespace of the hash<> function */ 13 | #undef HASH_NAMESPACE 14 | 15 | /* the location of or */ 16 | #undef HASH_SET_H 17 | 18 | /* Define to 1 if you have the header file. */ 19 | #undef HAVE_GOOGLE_MALLOC_EXTENSION_H 20 | 21 | /* define if the compiler has hash_map */ 22 | #undef HAVE_HASH_MAP 23 | 24 | /* define if the compiler has hash_set */ 25 | #undef HAVE_HASH_SET 26 | 27 | /* Define to 1 if you have the header file. */ 28 | #undef HAVE_INTTYPES_H 29 | 30 | /* Define to 1 if the system has the type `long long'. */ 31 | #undef HAVE_LONG_LONG 32 | 33 | /* Define to 1 if you have the `memcpy' function. */ 34 | #undef HAVE_MEMCPY 35 | 36 | /* Define to 1 if you have the `memmove' function. */ 37 | #undef HAVE_MEMMOVE 38 | 39 | /* Define to 1 if you have the header file. */ 40 | #undef HAVE_MEMORY_H 41 | 42 | /* define if the compiler implements namespaces */ 43 | #undef HAVE_NAMESPACES 44 | 45 | /* Define if you have POSIX threads libraries and header files. */ 46 | #undef HAVE_PTHREAD 47 | 48 | /* Define to 1 if you have the header file. */ 49 | #undef HAVE_STDINT_H 50 | 51 | /* Define to 1 if you have the header file. */ 52 | #undef HAVE_STDLIB_H 53 | 54 | /* Define to 1 if you have the header file. */ 55 | #undef HAVE_STRINGS_H 56 | 57 | /* Define to 1 if you have the header file. */ 58 | #undef HAVE_STRING_H 59 | 60 | /* Define to 1 if you have the header file. */ 61 | #undef HAVE_SYS_RESOURCE_H 62 | 63 | /* Define to 1 if you have the header file. */ 64 | #undef HAVE_SYS_STAT_H 65 | 66 | /* Define to 1 if you have the header file. */ 67 | #undef HAVE_SYS_TIME_H 68 | 69 | /* Define to 1 if you have the header file. */ 70 | #undef HAVE_SYS_TYPES_H 71 | 72 | /* Define to 1 if you have the header file. */ 73 | #undef HAVE_SYS_UTSNAME_H 74 | 75 | /* Define to 1 if the system has the type `uint16_t'. */ 76 | #undef HAVE_UINT16_T 77 | 78 | /* Define to 1 if you have the header file. */ 79 | #undef HAVE_UNISTD_H 80 | 81 | /* define if the compiler supports unordered_{map,set} */ 82 | #undef HAVE_UNORDERED_MAP 83 | 84 | /* Define to 1 if the system has the type `u_int16_t'. */ 85 | #undef HAVE_U_INT16_T 86 | 87 | /* Define to 1 if the system has the type `__uint16'. */ 88 | #undef HAVE___UINT16 89 | 90 | /* Name of package */ 91 | #undef PACKAGE 92 | 93 | /* Define to the address where bug reports for this package should be sent. */ 94 | #undef PACKAGE_BUGREPORT 95 | 96 | /* Define to the full name of this package. */ 97 | #undef PACKAGE_NAME 98 | 99 | /* Define to the full name and version of this package. */ 100 | #undef PACKAGE_STRING 101 | 102 | /* Define to the one symbol short name of this package. */ 103 | #undef PACKAGE_TARNAME 104 | 105 | /* Define to the home page for this package. */ 106 | #undef PACKAGE_URL 107 | 108 | /* Define to the version of this package. */ 109 | #undef PACKAGE_VERSION 110 | 111 | /* Define to necessary symbol if this constant uses a non-standard name on 112 | your system. */ 113 | #undef PTHREAD_CREATE_JOINABLE 114 | 115 | /* The system-provided hash function including the namespace. */ 116 | #undef SPARSEHASH_HASH 117 | 118 | /* The system-provided hash function, in namespace HASH_NAMESPACE. */ 119 | #undef SPARSEHASH_HASH_NO_NAMESPACE 120 | 121 | /* Define to 1 if you have the ANSI C header files. */ 122 | #undef STDC_HEADERS 123 | 124 | /* Version number of package */ 125 | #undef VERSION 126 | 127 | /* Stops putting the code inside the Google namespace */ 128 | #undef _END_GOOGLE_NAMESPACE_ 129 | 130 | /* Puts following code inside the Google namespace */ 131 | #undef _START_GOOGLE_NAMESPACE_ 132 | -------------------------------------------------------------------------------- /dbcore/sm-config.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../macros.h" 4 | #include "sm-config.h" 5 | #include "sm-thread.h" 6 | #include 7 | 8 | namespace ermia { 9 | namespace config { 10 | 11 | uint32_t arena_size_mb = 8; 12 | bool threadpool = true; 13 | bool tls_alloc = true; 14 | bool verbose = true; 15 | bool coro_tx = false; 16 | uint32_t coro_batch_size = 1; 17 | uint32_t coro_io_batch_size = 1; 18 | uint32_t coro_remote_batch_size = 1; 19 | bool coro_batch_schedule = false; 20 | uint32_t coro_scheduler = 0; 21 | uint32_t coro_io_scheduler = 0; 22 | uint32_t coro_remote_scheduler = 0; 23 | uint32_t coro_cold_queue_size = 1; 24 | uint32_t coro_cold_tx_threshold = 0; 25 | std::string coro_cold_tx_name = ""; 26 | uint32_t coro_check_cold_tx_interval = 1000; 27 | bool scan_with_it = false; 28 | std::string benchmark(""); 29 | uint32_t worker_threads = 0; 30 | uint32_t io_threads = 0; 31 | uint32_t remote_threads = 0; 32 | uint32_t benchmark_seconds = 30; 33 | uint64_t benchmark_transactions = 0; 34 | bool parallel_loading = false; 35 | bool retry_aborted_transactions = false; 36 | bool quick_bench_start = false; 37 | int backoff_aborted_transactions = 0; 38 | int numa_nodes = 0; 39 | int enable_gc = 0; 40 | std::string tmpfs_dir("/dev/shm"); 41 | int enable_safesnap = 0; 42 | int enable_ssi_read_only_opt = 0; 43 | uint64_t ssn_read_opt_threshold = SSN_READ_OPT_DISABLED; 44 | uint64_t log_buffer_mb = 8; 45 | uint64_t log_segment_mb = 16384; 46 | std::string log_dir(""); 47 | bool null_log_device = false; 48 | bool truncate_at_bench_start = false; 49 | bool htt_is_on = true; 50 | bool physical_workers_only = true; 51 | bool physical_io_workers_only = true; 52 | bool print_cpu_util = false; 53 | bool enable_perf = false; 54 | std::string perf_record_event(""); 55 | uint64_t node_memory_gb = 12; 56 | int recovery_warm_up_policy = WARM_UP_NONE; 57 | bool pcommit = false; 58 | uint32_t pcommit_queue_length = 50000; 59 | uint32_t pcommit_timeout_ms = 1000; 60 | uint64_t pcommit_size_kb = PAGE_SIZE; 61 | uint64_t pcommit_bytes = PAGE_SIZE * 1024; 62 | bool pcommit_thread = false; 63 | bool log_key_for_update = false; 64 | bool enable_chkpt = 0; 65 | uint64_t chkpt_interval = 50; 66 | bool phantom_prot = 0; 67 | double cycles_per_byte = 0; 68 | uint32_t state = kStateLoading; 69 | bool full_replay = false; 70 | uint32_t replay_threads = 0; 71 | uint32_t threads = 0; 72 | bool index_probe_only = false; 73 | bool numa_spread = false; 74 | bool kStateRunning = false; 75 | bool iouring_read_log = true; 76 | bool log_direct_io = true; 77 | std::string read_txn_type = "sequential"; 78 | uint64_t fetch_cold_tx_interval = 0; 79 | bool test_spinlock = false; 80 | uint64_t test_spinlock_cs = 0; 81 | bool test_coro_spinlock = false; 82 | bool hbm_arch = false; 83 | uint32_t max_numa_node = 0; 84 | uint32_t scheduling_policy = 1; 85 | uint64_t arrival_interval_us = 1000000; 86 | uint32_t main_queue_size = 1; 87 | uint32_t prioritized_queue_size = 1; 88 | uint32_t global_queue_size = 1; 89 | uint32_t max_preempted_cycle_pct = 100; 90 | uint32_t switch_threshold = 10; 91 | uint32_t latency_sample_rate = 0; 92 | uint32_t latency_sample_size = 100000; 93 | 94 | void init() { 95 | ALWAYS_ASSERT(threads); 96 | // Here [threads] refers to worker threads, so use the number of physical cores 97 | // to calculate # of numa nodes 98 | if (hbm_arch) { 99 | max_numa_node = numa_max_node() / 2; 100 | } else { 101 | max_numa_node = numa_max_node(); 102 | } 103 | 104 | if (numa_spread) { 105 | numa_nodes = threads > max_numa_node + 1 ? max_numa_node + 1 : threads; 106 | } else { 107 | uint32_t max = thread::cpu_cores.size() / (max_numa_node + 1); 108 | numa_nodes = (threads + max - 1) / max; 109 | ALWAYS_ASSERT(numa_nodes); 110 | } 111 | 112 | LOG(INFO) << "Workloads may run on " << numa_nodes << " nodes"; 113 | } 114 | 115 | void sanity_check() { 116 | LOG_IF(FATAL, tls_alloc && !threadpool) << "Cannot use TLS allocator without threadpool"; 117 | //ALWAYS_ASSERT(recover_functor); 118 | ALWAYS_ASSERT(numa_nodes || !threadpool); 119 | ALWAYS_ASSERT(!pcommit || pcommit_queue_length); 120 | } 121 | 122 | } // namespace config 123 | } // namespace ermia 124 | -------------------------------------------------------------------------------- /masstree/circular_int.hh: -------------------------------------------------------------------------------- 1 | /* Masstree 2 | * Eddie Kohler, Yandong Mao, Robert Morris 3 | * Copyright (c) 2012-2014 President and Fellows of Harvard College 4 | * Copyright (c) 2012-2014 Massachusetts Institute of Technology 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, subject to the conditions 9 | * listed in the Masstree LICENSE file. These conditions include: you must 10 | * preserve this copyright notice, and you cannot mention the copyright 11 | * holders in advertising related to the Software without their permission. 12 | * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This 13 | * notice is a summary of the Masstree LICENSE file; the license in that file 14 | * is legally binding. 15 | */ 16 | #ifndef KVDB_CIRCULAR_INT_HH 17 | #define KVDB_CIRCULAR_INT_HH 1 18 | #include "compiler.hh" 19 | 20 | template 21 | class circular_int { 22 | public: 23 | typedef typename std::make_unsigned::type value_type; 24 | typedef typename std::make_signed::type difference_type; 25 | 26 | circular_int() : v_() {} 27 | circular_int(T x) : v_(x) {} 28 | 29 | value_type value() const { return v_; } 30 | 31 | circular_int &operator++() { 32 | ++v_; 33 | return *this; 34 | } 35 | circular_int operator++(int) { 36 | ++v_; 37 | return circular_int(v_ - 1); 38 | } 39 | circular_int &operator--() { 40 | --v_; 41 | return *this; 42 | } 43 | circular_int operator--(int) { 44 | --v_; 45 | return circular_int(v_ + 1); 46 | } 47 | circular_int &operator+=(unsigned x) { 48 | v_ += x; 49 | return *this; 50 | } 51 | circular_int &operator+=(int x) { 52 | v_ += x; 53 | return *this; 54 | } 55 | circular_int &operator-=(unsigned x) { 56 | v_ -= x; 57 | return *this; 58 | } 59 | circular_int &operator-=(int x) { 60 | v_ -= x; 61 | return *this; 62 | } 63 | 64 | circular_int cmpxchg(circular_int expected, circular_int desired) { 65 | return ::cmpxchg(&v_, expected.v_, desired.v_); 66 | } 67 | circular_int cmpxchg(T expected, T desired) { 68 | return ::cmpxchg(&v_, expected, desired); 69 | } 70 | 71 | typedef value_type (circular_int::*unspecified_bool_type)() const; 72 | operator unspecified_bool_type() const { 73 | return v_ != 0 ? &circular_int::value : 0; 74 | } 75 | bool operator!() const { return v_ == 0; } 76 | 77 | circular_int operator+(unsigned x) const { 78 | return circular_int(v_ + x); 79 | } 80 | circular_int operator+(int x) const { return circular_int(v_ + x); } 81 | circular_int next_nonzero() const { 82 | value_type v = v_ + 1; 83 | return circular_int(v + !v); 84 | } 85 | static value_type next_nonzero(value_type x) { 86 | ++x; 87 | return x + !x; 88 | } 89 | circular_int operator-(unsigned x) const { 90 | return circular_int(v_ - x); 91 | } 92 | circular_int operator-(int x) const { return circular_int(v_ - x); } 93 | difference_type operator-(circular_int x) const { return v_ - x.v_; } 94 | 95 | bool operator==(circular_int x) const { return v_ == x.v_; } 96 | bool operator!=(circular_int x) const { return !(*this == x); } 97 | static bool less(value_type a, value_type b) { 98 | return difference_type(a - b) < 0; 99 | } 100 | static bool less_equal(value_type a, value_type b) { 101 | return difference_type(a - b) <= 0; 102 | } 103 | bool operator<(circular_int x) const { return less(v_, x.v_); } 104 | bool operator<=(circular_int x) const { return !less(x.v_, v_); } 105 | bool operator>=(circular_int x) const { return !less(v_, x.v_); } 106 | bool operator>(circular_int x) const { return less(x.v_, v_); } 107 | 108 | private: 109 | value_type v_; 110 | }; 111 | 112 | typedef circular_int kvepoch_t; 113 | 114 | template 115 | inline circular_int cmpxchg(circular_int *object, 116 | circular_int expected, 117 | circular_int desired) { 118 | return object->cmpxchg(expected, desired); 119 | } 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /dbcore/sm-object.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "dlog.h" 6 | #include "dlog-defs.h" 7 | #include "epoch.h" 8 | #include "sm-common.h" 9 | #include "sm-config.h" 10 | #include "sm-coroutine.h" 11 | #include "../varstr.h" 12 | #include "xid.h" 13 | 14 | 15 | namespace ermia { 16 | 17 | struct dbtuple; 18 | struct sm_log_recover_mgr; 19 | 20 | class Object { 21 | private: 22 | typedef epoch_mgr::epoch_num epoch_num; 23 | static const uint32_t kStatusMemory = 1; 24 | static const uint32_t kStatusStorage = 2; 25 | static const uint32_t kStatusLoading = 3; 26 | static const uint32_t kStatusDeleted = 4; 27 | 28 | // alloc_epoch_ and status_ must be the first two fields 29 | 30 | // When did we create this object? 31 | epoch_num alloc_epoch_; 32 | 33 | // Where exactly is the payload? 34 | uint32_t status_; 35 | 36 | // The object's permanent home in the log/chkpt 37 | fat_ptr pdest_; 38 | 39 | // The permanent home of the older version that's overwritten by me 40 | fat_ptr next_pdest_; 41 | 42 | // Volatile pointer to the next older version that's in memory. 43 | // There might be a gap between the versions represented by next_pdest_ 44 | // and next_volatile_. 45 | fat_ptr next_volatile_; 46 | 47 | // Commit timestamp of this version. Type is XID (CSN) before (after) 48 | // commit. 49 | fat_ptr csn_; 50 | 51 | public: 52 | static fat_ptr Create(const varstr* tuple_value, epoch_num epoch); 53 | 54 | Object() 55 | : alloc_epoch_(0), 56 | status_(kStatusMemory), 57 | pdest_(NULL_PTR), 58 | next_pdest_(NULL_PTR), 59 | next_volatile_(NULL_PTR) {} 60 | 61 | Object(fat_ptr pdest, fat_ptr next, epoch_num e, bool in_memory) 62 | : alloc_epoch_(e), 63 | status_(in_memory ? kStatusMemory : kStatusStorage), 64 | pdest_(pdest), 65 | next_pdest_(next), 66 | next_volatile_(NULL_PTR) {} 67 | 68 | inline bool IsDeleted() { return status_ == kStatusDeleted; } 69 | inline bool IsInMemory() { return status_ == kStatusMemory; } 70 | inline fat_ptr* GetPersistentAddressPtr() { return &pdest_; } 71 | inline fat_ptr GetPersistentAddress() { return pdest_; } 72 | inline void SetPersistentAddress(fat_ptr ptr) { pdest_._ptr = ptr._ptr; } 73 | inline fat_ptr GetCSN() { return csn_; } 74 | inline void SetCSN(fat_ptr csnptr) { volatile_write(csn_._ptr, csnptr._ptr); } 75 | inline fat_ptr GetNextPersistent() { return volatile_read(next_pdest_); } 76 | inline fat_ptr* GetNextPersistentPtr() { return &next_pdest_; } 77 | inline fat_ptr GetNextVolatile() { return volatile_read(next_volatile_); } 78 | inline fat_ptr* GetNextVolatilePtr() { return &next_volatile_; } 79 | inline void SetNextPersistent(fat_ptr next) { volatile_write(next_pdest_, next); } 80 | inline void SetNextVolatile(fat_ptr next) { volatile_write(next_volatile_, next); } 81 | inline epoch_num GetAllocateEpoch() { return alloc_epoch_; } 82 | inline void SetAllocateEpoch(epoch_num e) { alloc_epoch_ = e; } 83 | inline char* GetPayload() { return (char*)((char*)this + sizeof(Object)); } 84 | inline void SetStatus(uint32_t s) { volatile_write(status_, s); } 85 | inline PROMISE(dbtuple*) GetPinnedTuple(transaction *xct) { 86 | if (IsDeleted()) { 87 | RETURN nullptr; 88 | } 89 | AWAIT Pin(xct); 90 | RETURN (dbtuple*)GetPayload(); 91 | } 92 | inline dbtuple* SyncGetPinnedTuple(transaction *xct) { 93 | if (IsDeleted()) { 94 | return nullptr; 95 | } 96 | SyncPin(xct); 97 | return (dbtuple*)GetPayload(); 98 | } 99 | 100 | static fat_ptr GenerateCsnPtr(uint64_t csn); 101 | static PROMISE(dbtuple *) LoadFromStorage(transaction *xct, fat_ptr pdest, Object *object); 102 | static dbtuple* SyncLoadFromStorage(transaction *xct, fat_ptr pdest, Object *object); 103 | static ermia::coro::task TaskLoadFromStorage(transaction *xct, fat_ptr pdest, Object *object); 104 | PROMISE(void) Pin(transaction *xct); // Make sure the payload is in memory 105 | void SyncPin(transaction *xct); 106 | 107 | static inline void PrefetchHeader(Object *p) { 108 | uint32_t i = 0; 109 | do { 110 | ::prefetch((const char *)(p + i)); 111 | i += CACHE_LINE_SIZE; 112 | } while (i < sizeof(Object)); 113 | } 114 | 115 | }; 116 | } // namespace ermia 117 | -------------------------------------------------------------------------------- /masstree/btree_leaflink.hh: -------------------------------------------------------------------------------- 1 | /* Masstree 2 | * Eddie Kohler, Yandong Mao, Robert Morris 3 | * Copyright (c) 2012-2014 President and Fellows of Harvard College 4 | * Copyright (c) 2012-2014 Massachusetts Institute of Technology 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, subject to the conditions 9 | * listed in the Masstree LICENSE file. These conditions include: you must 10 | * preserve this copyright notice, and you cannot mention the copyright 11 | * holders in advertising related to the Software without their permission. 12 | * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This 13 | * notice is a summary of the Masstree LICENSE file; the license in that file 14 | * is legally binding. 15 | */ 16 | #ifndef BTREE_LEAFLINK_HH 17 | #define BTREE_LEAFLINK_HH 1 18 | #include "compiler.hh" 19 | 20 | /** @brief Operations to manage linked lists of B+tree leaves. 21 | 22 | N is the type of nodes. CONCURRENT is true to make operations 23 | concurrency-safe (e.g. compare-and-swaps, fences), false to leave them 24 | unsafe (only OK on single threaded code, but faster). */ 25 | template 26 | struct btree_leaflink {}; 27 | 28 | // This is the normal version of btree_leaflink; it uses lock-free linked list 29 | // operations. 30 | template 31 | struct btree_leaflink { 32 | private: 33 | static inline N *mark(N *n) { 34 | return reinterpret_cast(reinterpret_cast(n) + 1); 35 | } 36 | static inline bool is_marked(N *n) { 37 | return reinterpret_cast(n) & 1; 38 | } 39 | template 40 | static inline N *lock_next(N *n, SF spin_function) { 41 | while (1) { 42 | N *next = n->next_.ptr; 43 | if (!next || 44 | (!is_marked(next) && bool_cmpxchg(&n->next_.ptr, next, mark(next)))) 45 | return next; 46 | spin_function(); 47 | } 48 | } 49 | 50 | public: 51 | /** @brief Insert a new node @a nr at the right of node @a n. 52 | @pre @a n is locked. 53 | 54 | Concurrency correctness: Ensures that all "next" pointers are always 55 | valid, even if @a n's successor is deleted concurrently. */ 56 | static void link_split(N *n, N *nr) { 57 | link_split(n, nr, relax_fence_function()); 58 | } 59 | /** @overload */ 60 | template 61 | static void link_split(N *n, N *nr, SF spin_function) { 62 | nr->prev_ = n; 63 | N *next = lock_next(n, spin_function); 64 | nr->next_.ptr = next; 65 | if (next) next->prev_ = nr; 66 | fence(); 67 | n->next_.ptr = nr; 68 | } 69 | 70 | /** @brief Unlink @a n from the list. 71 | @pre @a n is locked. 72 | 73 | Concurrency correctness: Works even in the presence of concurrent 74 | splits and deletes. */ 75 | static void unlink(N *n) { unlink(n, relax_fence_function()); } 76 | /** @overload */ 77 | template 78 | static void unlink(N *n, SF spin_function) { 79 | // Assume node order A <-> N <-> B. Since n is locked, n cannot split; 80 | // next node will always be B or one of its successors. 81 | N *next = lock_next(n, spin_function); 82 | N *prev; 83 | while (1) { 84 | prev = n->prev_; 85 | if (bool_cmpxchg(&prev->next_.ptr, n, mark(n))) break; 86 | spin_function(); 87 | } 88 | if (next) next->prev_ = prev; 89 | fence(); 90 | prev->next_.ptr = next; 91 | } 92 | }; 93 | 94 | // This is the single-threaded-only fast version of btree_leaflink. 95 | template 96 | struct btree_leaflink { 97 | static void link_split(N *n, N *nr) { link_split(n, nr, do_nothing()); } 98 | template 99 | static void link_split(N *n, N *nr, SF) { 100 | nr->prev_ = n; 101 | nr->next_.ptr = n->next_.ptr; 102 | n->next_.ptr = nr; 103 | if (nr->next_.ptr) nr->next_.ptr->prev_ = nr; 104 | } 105 | static void unlink(N *n) { unlink(n, do_nothing()); } 106 | template 107 | static void unlink(N *n, SF) { 108 | if (n->next_.ptr) n->next_.ptr->prev_ = n->prev_; 109 | n->prev_->next_.ptr = n->next_.ptr; 110 | } 111 | }; 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /dbcore/defer.h: -------------------------------------------------------------------------------- 1 | // -*- mode:c++ -*- 2 | #ifndef __DEFER_H 3 | #define __DEFER_H 4 | 5 | /* This header provides support for a class of DEFER macros, which can 6 | be used to register code that should run if the current block goes 7 | out of scope for any reason. That includes cases where the scope 8 | exits normally, when an exception is thrown, and even because a 9 | goto transfers control above the location of the DEFER. 10 | 11 | This strong "always runs" guarantee makes it easy to express 12 | try..finally semantics. The behavior is similar to the effect of a 13 | destructor call in the C++ RAII idiom, but eliminates the need to 14 | define RAII classes for simple or one-off uses. It also improves 15 | code readability by making very explicit the programmers intention 16 | (acquire, followed immediately by a deferred release), rather than 17 | hiding the acquire/release sementics in some other chunk of code 18 | (potentially declared far away from the use site). 19 | 20 | Unlike destructors, execution of the deferred code can also be made 21 | conditional. One extremely useful variant is to condition deferred 22 | execution on the scope exiting before execution reaches a certain 23 | point in the code. This would be similar to specifying a catch(...) 24 | { do_cleanup(); throw; } clause, but is far more efficient. In the 25 | common case, the compiler actually moves the deferred code to the 26 | stack unwind code, leaving the main code path completely 27 | unaffected. 28 | 29 | WARNING: this furequires several C++11 features, including lambdas, 30 | auto, and decltype 31 | */ 32 | 33 | /* Execute @stmt when the current scope exits for any reason. 34 | 35 | NOTE: deferred actions that are still in scope when a function 36 | returns execute *after* the function's return value has been 37 | computed. In other words, the following prints "10" and "0": 38 | 39 | int foo(int *ptr) { 40 | DEFER(*ptr = 0); 41 | return *ptr; 42 | } 43 | int main() { 44 | int x = 10; 45 | printf("%d\n", foo(&x)); 46 | printf("%d\n", x); 47 | } 48 | */ 49 | #define DEFER(stmt) XDEFER([&] { stmt; }) 50 | 51 | /*Invoke the lambda @x() when the current scope exits for any reason. 52 | */ 53 | #define XDEFER(x) _XDEFER(x, __LINE__) 54 | 55 | #define _XDEFER(x, line) __XDEFER(x, line) 56 | 57 | #define __XDEFER(x, line) \ 58 | auto __x##line = [&] { (x)(); }; \ 59 | auto __defer##line = __defer(__x##line) 60 | 61 | /* Define a variable, @commit, initialized to false, and register a 62 | deferred action; the action will be performed when the current 63 | scope exits, unless @commit becomes true before then. 64 | 65 | Most of the time, the compiler can statically analyze the behavior 66 | of @commit and host the taken/not-taken branches into main and 67 | unwind code paths as appropriate (eliminating the conditional 68 | branch in the code that would otherwise be required). 69 | */ 70 | #define DEFER_UNLESS(commit, x) \ 71 | bool commit = false; \ 72 | XDEFER_UNLESS(commit, x) 73 | 74 | /* Similar to DEFER_UNLESS, but uses an existing @commit variable 75 | rather than declaring a new one. 76 | 77 | Useful for predicating multiple deferred actions on a single event. 78 | 79 | Less useful in the general case, because the compiler usually can't 80 | rule out statically the possibility that @commit might be false 81 | when the main code path exits, and so would have to leave a 82 | conditional branch in place. 83 | */ 84 | #define XDEFER_UNLESS(commit, x) \ 85 | XDEFER([&] { \ 86 | if (not(commit)) { \ 87 | x; \ 88 | } \ 89 | }) 90 | 91 | /* Similar to XDEFER_UNLESS, but the action [x] will only be performed 92 | if the existing variable named by [commit] evalutes to true. 93 | */ 94 | #define XDEFER_IF(commit, x) \ 95 | XDEFER([&] { \ 96 | if (commit) { \ 97 | x; \ 98 | } \ 99 | }) 100 | 101 | /* Helper class that supports the above macros */ 102 | template 103 | struct __defer { 104 | T &fn; 105 | __defer(T &fn) : fn(fn) {} 106 | ~__defer() { fn(); } 107 | __defer(const __defer &) = default; 108 | }; 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/sparsehash/internal/libc_allocator_with_realloc.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // --- 31 | 32 | #ifndef UTIL_GTL_LIBC_ALLOCATOR_WITH_REALLOC_H_ 33 | #define UTIL_GTL_LIBC_ALLOCATOR_WITH_REALLOC_H_ 34 | 35 | #include 36 | #include // for malloc/realloc/free 37 | #include // for ptrdiff_t 38 | #include // for placement new 39 | 40 | _START_GOOGLE_NAMESPACE_ 41 | 42 | template 43 | class libc_allocator_with_realloc { 44 | public: 45 | typedef T value_type; 46 | typedef size_t size_type; 47 | typedef ptrdiff_t difference_type; 48 | 49 | typedef T* pointer; 50 | typedef const T* const_pointer; 51 | typedef T& reference; 52 | typedef const T& const_reference; 53 | 54 | libc_allocator_with_realloc() {} 55 | libc_allocator_with_realloc(const libc_allocator_with_realloc&) {} 56 | ~libc_allocator_with_realloc() {} 57 | 58 | pointer address(reference r) const { return &r; } 59 | const_pointer address(const_reference r) const { return &r; } 60 | 61 | pointer allocate(size_type n, const_pointer = 0) { 62 | return static_cast(malloc(n * sizeof(value_type))); 63 | } 64 | void deallocate(pointer p, size_type) { 65 | free(p); 66 | } 67 | pointer reallocate(pointer p, size_type n) { 68 | return static_cast(realloc(p, n * sizeof(value_type))); 69 | } 70 | 71 | size_type max_size() const { 72 | return static_cast(-1) / sizeof(value_type); 73 | } 74 | 75 | void construct(pointer p, const value_type& val) { 76 | new(p) value_type(val); 77 | } 78 | void destroy(pointer p) { p->~value_type(); } 79 | 80 | template 81 | libc_allocator_with_realloc(const libc_allocator_with_realloc&) {} 82 | 83 | template 84 | struct rebind { 85 | typedef libc_allocator_with_realloc other; 86 | }; 87 | }; 88 | 89 | // libc_allocator_with_realloc specialization. 90 | template<> 91 | class libc_allocator_with_realloc { 92 | public: 93 | typedef void value_type; 94 | typedef size_t size_type; 95 | typedef ptrdiff_t difference_type; 96 | typedef void* pointer; 97 | typedef const void* const_pointer; 98 | 99 | template 100 | struct rebind { 101 | typedef libc_allocator_with_realloc other; 102 | }; 103 | }; 104 | 105 | template 106 | inline bool operator==(const libc_allocator_with_realloc&, 107 | const libc_allocator_with_realloc&) { 108 | return true; 109 | } 110 | 111 | template 112 | inline bool operator!=(const libc_allocator_with_realloc&, 113 | const libc_allocator_with_realloc&) { 114 | return false; 115 | } 116 | 117 | _END_GOOGLE_NAMESPACE_ 118 | 119 | #endif // UTIL_GTL_LIBC_ALLOCATOR_WITH_REALLOC_H_ 120 | -------------------------------------------------------------------------------- /third-party/gflags/include/gflags/gflags_gflags.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Andreas Schuh 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // ----------------------------------------------------------------------------- 31 | // Imports the gflags library symbols into an alternative/deprecated namespace. 32 | 33 | #ifndef GFLAGS_GFLAGS_H_ 34 | # error The internal header gflags_gflags.h may only be included by gflags.h 35 | #endif 36 | 37 | #ifndef GFLAGS_NS_GFLAGS_H_ 38 | #define GFLAGS_NS_GFLAGS_H_ 39 | 40 | 41 | namespace gflags { 42 | 43 | 44 | using GFLAGS_NAMESPACE::int32; 45 | using GFLAGS_NAMESPACE::uint32; 46 | using GFLAGS_NAMESPACE::int64; 47 | using GFLAGS_NAMESPACE::uint64; 48 | 49 | using GFLAGS_NAMESPACE::RegisterFlagValidator; 50 | using GFLAGS_NAMESPACE::CommandLineFlagInfo; 51 | using GFLAGS_NAMESPACE::GetAllFlags; 52 | using GFLAGS_NAMESPACE::ShowUsageWithFlags; 53 | using GFLAGS_NAMESPACE::ShowUsageWithFlagsRestrict; 54 | using GFLAGS_NAMESPACE::DescribeOneFlag; 55 | using GFLAGS_NAMESPACE::SetArgv; 56 | using GFLAGS_NAMESPACE::GetArgvs; 57 | using GFLAGS_NAMESPACE::GetArgv; 58 | using GFLAGS_NAMESPACE::GetArgv0; 59 | using GFLAGS_NAMESPACE::GetArgvSum; 60 | using GFLAGS_NAMESPACE::ProgramInvocationName; 61 | using GFLAGS_NAMESPACE::ProgramInvocationShortName; 62 | using GFLAGS_NAMESPACE::ProgramUsage; 63 | using GFLAGS_NAMESPACE::VersionString; 64 | using GFLAGS_NAMESPACE::GetCommandLineOption; 65 | using GFLAGS_NAMESPACE::GetCommandLineFlagInfo; 66 | using GFLAGS_NAMESPACE::GetCommandLineFlagInfoOrDie; 67 | using GFLAGS_NAMESPACE::FlagSettingMode; 68 | using GFLAGS_NAMESPACE::SET_FLAGS_VALUE; 69 | using GFLAGS_NAMESPACE::SET_FLAG_IF_DEFAULT; 70 | using GFLAGS_NAMESPACE::SET_FLAGS_DEFAULT; 71 | using GFLAGS_NAMESPACE::SetCommandLineOption; 72 | using GFLAGS_NAMESPACE::SetCommandLineOptionWithMode; 73 | using GFLAGS_NAMESPACE::FlagSaver; 74 | using GFLAGS_NAMESPACE::CommandlineFlagsIntoString; 75 | using GFLAGS_NAMESPACE::ReadFlagsFromString; 76 | using GFLAGS_NAMESPACE::AppendFlagsIntoFile; 77 | using GFLAGS_NAMESPACE::ReadFromFlagsFile; 78 | using GFLAGS_NAMESPACE::BoolFromEnv; 79 | using GFLAGS_NAMESPACE::Int32FromEnv; 80 | using GFLAGS_NAMESPACE::Uint32FromEnv; 81 | using GFLAGS_NAMESPACE::Int64FromEnv; 82 | using GFLAGS_NAMESPACE::Uint64FromEnv; 83 | using GFLAGS_NAMESPACE::DoubleFromEnv; 84 | using GFLAGS_NAMESPACE::StringFromEnv; 85 | using GFLAGS_NAMESPACE::SetUsageMessage; 86 | using GFLAGS_NAMESPACE::SetVersionString; 87 | using GFLAGS_NAMESPACE::ParseCommandLineNonHelpFlags; 88 | using GFLAGS_NAMESPACE::HandleCommandLineHelpFlags; 89 | using GFLAGS_NAMESPACE::AllowCommandLineReparsing; 90 | using GFLAGS_NAMESPACE::ReparseCommandLineNonHelpFlags; 91 | using GFLAGS_NAMESPACE::ShutDownCommandLineFlags; 92 | using GFLAGS_NAMESPACE::FlagRegisterer; 93 | 94 | #ifndef SWIG 95 | using GFLAGS_NAMESPACE::ParseCommandLineFlags; 96 | #endif 97 | 98 | 99 | } // namespace gflags 100 | 101 | 102 | #endif // GFLAGS_NS_GFLAGS_H_ 103 | -------------------------------------------------------------------------------- /masstree/str.hh: -------------------------------------------------------------------------------- 1 | /* Masstree 2 | * Eddie Kohler, Yandong Mao, Robert Morris 3 | * Copyright (c) 2012-2013 President and Fellows of Harvard College 4 | * Copyright (c) 2012-2013 Massachusetts Institute of Technology 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, subject to the conditions 9 | * listed in the Masstree LICENSE file. These conditions include: you must 10 | * preserve this copyright notice, and you cannot mention the copyright 11 | * holders in advertising related to the Software without their permission. 12 | * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This 13 | * notice is a summary of the Masstree LICENSE file; the license in that file 14 | * is legally binding. 15 | */ 16 | #ifndef STR_HH 17 | #define STR_HH 18 | #include "compiler.hh" 19 | #include "string_base.hh" 20 | #include 21 | #include 22 | namespace lcdf { 23 | 24 | struct Str : public String_base { 25 | typedef Str substring_type; 26 | typedef Str argument_type; 27 | 28 | const char *s; 29 | int len; 30 | 31 | Str() : s(0), len(0) {} 32 | template 33 | Str(const String_base &x) 34 | : s(x.data()), len(x.length()) {} 35 | Str(const char *s_) : s(s_), len(strlen(s_)) {} 36 | Str(const char *s_, int len_) : s(s_), len(len_) {} 37 | Str(const unsigned char *s_, int len_) 38 | : s(reinterpret_cast(s_)), len(len_) {} 39 | Str(const char *first, const char *last) : s(first), len(last - first) { 40 | precondition(first <= last); 41 | } 42 | Str(const unsigned char *first, const unsigned char *last) 43 | : s(reinterpret_cast(first)), len(last - first) { 44 | precondition(first <= last); 45 | } 46 | Str(const std::string &str) : s(str.data()), len(str.length()) {} 47 | Str(const uninitialized_type &unused) { (void)unused; } 48 | 49 | static const Str maxkey; 50 | 51 | void assign() { 52 | s = 0; 53 | len = 0; 54 | } 55 | template 56 | void assign(const String_base &x) { 57 | s = x.data(); 58 | len = x.length(); 59 | } 60 | void assign(const char *s_) { 61 | s = s_; 62 | len = strlen(s_); 63 | } 64 | void assign(const char *s_, int len_) { 65 | s = s_; 66 | len = len_; 67 | } 68 | 69 | const char *data() const { return s; } 70 | int length() const { return len; } 71 | char *mutable_data() { return const_cast(s); } 72 | 73 | Str prefix(int lenx) const { return Str(s, lenx < len ? lenx : len); } 74 | Str substring(const char *first, const char *last) const { 75 | if (first <= last && first >= s && last <= s + len) 76 | return Str(first, last); 77 | else 78 | return Str(); 79 | } 80 | Str substring(const unsigned char *first, const unsigned char *last) const { 81 | const unsigned char *u = reinterpret_cast(s); 82 | if (first <= last && first >= u && last <= u + len) 83 | return Str(first, last); 84 | else 85 | return Str(); 86 | } 87 | Str fast_substring(const char *first, const char *last) const { 88 | assert(begin() <= first && first <= last && last <= end()); 89 | return Str(first, last); 90 | } 91 | Str fast_substring(const unsigned char *first, 92 | const unsigned char *last) const { 93 | assert(ubegin() <= first && first <= last && last <= uend()); 94 | return Str(first, last); 95 | } 96 | Str ltrim() const { return String_generic::ltrim(*this); } 97 | Str rtrim() const { return String_generic::rtrim(*this); } 98 | Str trim() const { return String_generic::trim(*this); } 99 | 100 | long to_i() const { // XXX does not handle negative 101 | long x = 0; 102 | int p; 103 | for (p = 0; p < len && s[p] >= '0' && s[p] <= '9'; ++p) 104 | x = (x * 10) + s[p] - '0'; 105 | return p == len && p != 0 ? x : -1; 106 | } 107 | }; 108 | 109 | struct inline_string : public String_base { 110 | int len; 111 | char s[0]; 112 | 113 | const char *data() const { return s; } 114 | int length() const { return len; } 115 | 116 | size_t size() const { return sizeof(inline_string) + len; } 117 | static size_t size(int len) { return sizeof(inline_string) + len; } 118 | }; 119 | 120 | } // namespace lcdf 121 | 122 | LCDF_MAKE_STRING_HASH(lcdf::Str) 123 | LCDF_MAKE_STRING_HASH(lcdf::inline_string) 124 | #endif 125 | -------------------------------------------------------------------------------- /txn-mvocc.cc: -------------------------------------------------------------------------------- 1 | #ifdef MVOCC 2 | 3 | #include "macros.h" 4 | #include "txn.h" 5 | #include "dbcore/serial.h" 6 | #include "engine.h" 7 | 8 | namespace ermia { 9 | 10 | rc_t transaction::mvocc_commit() { 11 | ASSERT(log); 12 | // get clsn, abort if failed 13 | xc->end = log->pre_commit().offset(); 14 | if (xc->end == 0) { 15 | return rc_t{RC_ABORT_INTERNAL}; 16 | } 17 | 18 | if (config::phantom_prot && !MasstreeCheckPhantom()) { 19 | return rc_t{RC_ABORT_PHANTOM}; 20 | } 21 | 22 | // Just need to check read-set 23 | for (uint32_t i = 0; i < read_set.size(); ++i) { 24 | auto &r = read_set[i]; 25 | check_backedge: 26 | fat_ptr successor_clsn = volatile_read(r->sstamp); 27 | if (!successor_clsn.offset()) { 28 | continue; 29 | } 30 | 31 | // Already overwritten, see if this is a back-edge, i.e., committed before 32 | // me 33 | if (successor_clsn.asi_type() == fat_ptr::ASI_LOG) { 34 | if (successor_clsn.offset() < xc->end) { 35 | return rc_t{RC_ABORT_SERIAL}; 36 | } 37 | } else { 38 | XID successor_xid = XID::from_ptr(successor_clsn); 39 | TXN::xid_context *successor_xc = TXN::xid_get_context(successor_xid); 40 | if (!successor_xc) { 41 | goto check_backedge; 42 | } 43 | if (volatile_read(successor_xc->owner) == xc->owner) { // myself 44 | continue; 45 | } 46 | auto successor_state = volatile_read(successor_xc->state); 47 | if (!successor_xc->verify_owner(successor_xid)) { 48 | goto check_backedge; 49 | } 50 | if (successor_state == TXN::TXN_ACTIVE) { 51 | // Not yet in pre-commit, skip 52 | continue; 53 | } 54 | // Already in pre-commit or committed, definitely has (or will have) 55 | // cstamp 56 | uint64_t successor_end = 0; 57 | bool should_continue = false; 58 | while (!successor_end) { 59 | auto s = volatile_read(successor_xc->end); 60 | successor_state = volatile_read(successor_xc->state); 61 | if (not successor_xc->verify_owner(successor_xid)) { 62 | goto check_backedge; 63 | } 64 | if (successor_state == TXN::TXN_ABRTD) { 65 | // If there's a new overwriter, it must have a cstamp larger than mine 66 | should_continue = true; 67 | break; 68 | } 69 | ALWAYS_ASSERT(successor_state == TXN::TXN_CMMTD || 70 | successor_state == TXN::TXN_COMMITTING); 71 | successor_end = s; 72 | } 73 | if (should_continue) { 74 | continue; 75 | } 76 | if (successor_end < xc->end) { 77 | return rc_t{RC_ABORT_SERIAL}; 78 | } 79 | } 80 | } 81 | 82 | log->commit(NULL); // will populate log block 83 | 84 | // post-commit cleanup: install clsn to tuples 85 | // (traverse write-tuple) 86 | // stuff clsn in tuples in write-set 87 | auto clsn = xc->end; 88 | for (uint32_t i = 0; i < write_set.size(); ++i) { 89 | auto &w = write_set[i]; 90 | Object *object = w.get_object(); 91 | dbtuple *tuple = (dbtuple *)object->GetPayload(); 92 | ASSERT(w.entry); 93 | tuple->DoWrite(); 94 | dbtuple *overwritten_tuple = tuple->NextVolatile(); 95 | fat_ptr clsn_ptr = object->GenerateClsnPtr(clsn); 96 | if (overwritten_tuple) { 97 | ASSERT(overwritten_tuple->sstamp.asi_type() == fat_ptr::ASI_XID); 98 | ASSERT(XID::from_ptr(overwritten_tuple->sstamp) == xid); 99 | volatile_write(overwritten_tuple->sstamp, clsn_ptr); 100 | ASSERT(overwritten_tuple->sstamp.asi_type() == fat_ptr::ASI_LOG); 101 | ASSERT(overwritten_tuple->sstamp.offset() == clsn_ptr.offset()); 102 | } 103 | object->SetClsn(clsn_ptr); 104 | ASSERT(tuple->GetObject()->GetClsn().asi_type() == fat_ptr::ASI_LOG); 105 | #ifndef NDEBUG 106 | Object *obj = tuple->GetObject(); 107 | fat_ptr pdest = obj->GetPersistentAddress(); 108 | ASSERT((pdest == NULL_PTR and not tuple->size) or 109 | (pdest.asi_type() == fat_ptr::ASI_LOG)); 110 | #endif 111 | } 112 | 113 | // NOTE: make sure this happens after populating log block, 114 | // otherwise readers will see inconsistent data! 115 | // This is where (committed) tuple data are made visible to readers 116 | volatile_write(xc->state, TXN::TXN_CMMTD); 117 | return rc_t{RC_TRUE}; 118 | } 119 | 120 | rc_t transaction::mvocc_read(dbtuple *tuple) { 121 | read_set.emplace_back(tuple); 122 | return rc_t{RC_TRUE}; 123 | } 124 | } // namespace ermia 125 | 126 | #endif // MVOCC 127 | -------------------------------------------------------------------------------- /masstree/masstree.hh: -------------------------------------------------------------------------------- 1 | /* Masstree 2 | * Eddie Kohler, Yandong Mao, Robert Morris 3 | * Copyright (c) 2012-2014 President and Fellows of Harvard College 4 | * Copyright (c) 2012-2014 Massachusetts Institute of Technology 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, subject to the conditions 9 | * listed in the Masstree LICENSE file. These conditions include: you must 10 | * preserve this copyright notice, and you cannot mention the copyright 11 | * holders in advertising related to the Software without their permission. 12 | * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This 13 | * notice is a summary of the Masstree LICENSE file; the license in that file 14 | * is legally binding. 15 | */ 16 | #ifndef MASSTREE_HH 17 | #define MASSTREE_HH 18 | #include "ksearch.hh" 19 | #include "str.hh" 20 | 21 | #include "../dbcore/sm-oid.h" 22 | #include "../dbcore/xid.h" 23 | #include "../dbcore/sm-coroutine.h" 24 | #include "../macros.h" 25 | 26 | namespace Masstree { 27 | using lcdf::Str; 28 | using lcdf::String; 29 | 30 | template class value_print; 31 | 32 | template struct nodeparams { 33 | static constexpr int leaf_width = LW; 34 | static constexpr int internode_width = IW; 35 | static constexpr bool concurrent = true; 36 | static constexpr bool prefetch = true; 37 | static constexpr int bound_method = bound_method_binary; 38 | static constexpr int debug_level = 0; 39 | static constexpr bool printable_keys = true; 40 | typedef uint64_t ikey_type; 41 | }; 42 | 43 | template constexpr int nodeparams::leaf_width; 44 | template constexpr int nodeparams::internode_width; 45 | template constexpr int nodeparams::debug_level; 46 | 47 | template class node_base; 48 | template class leaf; 49 | template class internode; 50 | template class leafvalue; 51 | template class key; 52 | template class basic_table; 53 | template class unlocked_tcursor; 54 | template class tcursor; 55 | 56 | template struct scan_info; 57 | 58 | template class basic_table { 59 | public: 60 | typedef P param_type; 61 | typedef node_base

node_type; 62 | typedef leaf

leaf_type; 63 | typedef typename P::value_type value_type; 64 | typedef typename P::contextinfo_type contextinfo; 65 | typedef unlocked_tcursor

unlocked_cursor_type; 66 | typedef tcursor

cursor_type; 67 | 68 | inline basic_table(); 69 | 70 | void initialize(contextinfo &ti); 71 | void destroy(contextinfo &ti); 72 | 73 | inline node_type *root() const; 74 | inline node_type *fix_root(); 75 | 76 | PROMISE(bool) get(Str key, value_type &value, contextinfo &ti) const; 77 | 78 | template 79 | PROMISE(int) scan(Str firstkey, bool matchfirst, F &scanner, 80 | ermia::TXN::xid_context *xc, contextinfo &ti) const; 81 | template 82 | PROMISE(int) rscan(Str firstkey, bool matchfirst, F &scanner, 83 | ermia::TXN::xid_context *xc, contextinfo &ti) const; 84 | 85 | template inline int modify(Str key, F &f, contextinfo &ti); 86 | template inline int modify_insert(Str key, F &f, contextinfo &ti); 87 | 88 | inline void print(FILE *f = 0, int indent = 0) const; 89 | inline void set_tuple_array(ermia::oid_array *oa) { tuple_array_ = oa; } 90 | inline void set_pdest_array(ermia::oid_array *oa) { pdest_array_ = oa; } 91 | inline node_type *get_root() const { return root_; } 92 | 93 | node_type *root_; 94 | ermia::oid_array *tuple_array_; 95 | ermia::oid_array *pdest_array_; 96 | 97 | public: 98 | template 99 | PROMISE(int) scan(H helper, Str firstkey, bool matchfirst, F &scanner, 100 | ermia::TXN::xid_context *xc, contextinfo &ti) const; 101 | 102 | template 103 | PROMISE(bool) scan_init_or_next_value(H helper, F &scanner, 104 | ermia::TXN::xid_context *xc, 105 | contextinfo &ti, 106 | scan_info

*si) const; 107 | 108 | friend class unlocked_tcursor

; 109 | friend class tcursor

; 110 | }; 111 | 112 | } // namespace Masstree 113 | #endif 114 | -------------------------------------------------------------------------------- /dbcore/burt-hash.py: -------------------------------------------------------------------------------- 1 | # see http://burtleburtle.net/bob/hash/integer.html 2 | hash_constants = ''' 3 | 38 113 41 68 35 74 111 4 | 38 113 42 69 35 73 112 5 | 38 114 9 100 35 107 46 6 | 38 114 11 66 8 68 112 7 | 38 114 42 69 35 73 112 8 | 38 114 78 37 71 35 111 9 | 39 113 41 68 2 74 112 10 | 39 114 9 101 2 107 17 11 | 39 114 9 101 2 107 49 12 | 39 114 37 99 39 109 50 13 | 39 115 36 67 38 44 112 14 | 39 115 37 70 35 110 11 15 | 39 115 41 74 36 67 111 16 | 39 116 4 104 6 107 16 17 | 39 116 10 101 8 75 113 18 | 40 113 12 99 39 69 112 19 | 40 113 13 99 6 69 113 20 | 40 113 38 101 2 106 16 21 | 40 113 38 101 2 106 48 22 | 40 114 3 102 8 109 15 23 | 40 114 37 99 7 77 113 24 | 41 113 11 100 7 69 111 25 | 42 114 44 99 38 72 113 26 | 43 115 7 101 3 109 48 27 | 44 114 36 105 38 108 16 28 | 44 114 37 102 35 107 16 29 | 44 114 41 101 2 109 16 30 | 45 113 37 102 3 108 47 31 | 45 113 37 105 35 104 17 32 | 45 113 37 105 35 104 47 33 | 45 113 39 99 37 76 111 34 | 45 113 42 101 2 109 46 35 | 45 113 42 101 2 109 50 36 | 46 113 42 101 35 110 47 37 | 46 113 42 101 35 110 50 38 | ''' 39 | 40 | def op2code(c, xtype='uint32_t'): 41 | c = int(c) 42 | if xtype is '__v4si': 43 | if c < 32: 44 | return 'x[0] += x[0] << %d; x[1] += x[1] << %d; x[2] += x[2] << %d; x[3] += x[3] << %d' % (c, c, c, c) 45 | elif c < 64: 46 | return 'x[0] += x[0] << %d; x[1] += x[1] << %d; x[2] += x[2] << %d; x[3] += x[3] << %d' % (c-32, c-32, c-32, c-32) 47 | elif c < 96: 48 | return 'x[0] += x[0] << %d; x[1] += x[1] << %d; x[2] += x[2] << %d; x[3] += x[3] << %d' % (c-64, c-64, c-64, c-64) 49 | else: 50 | return 'x[0] += x[0] << %d; x[1] += x[1] << %d; x[2] += x[2] << %d; x[3] += x[3] << %d' % (c-96, c-96, c-96, c-96) 51 | else: 52 | if c < 32: 53 | return 'x += x << %d' % c 54 | elif c < 64: 55 | return 'x -= x << %d' % (c-32) 56 | elif c < 96: 57 | return 'x ^= x << %d' % (c-64) 58 | else: 59 | return 'x ^= x >> %d' % (c-96) 60 | 61 | def emit_python(name, clist, xtype): 62 | print 'def %s(x):' % name 63 | for c in clist: 64 | print '\t%s' % op2code(c, xtype) 65 | print '\treturn x\n' 66 | 67 | def emit_c(name, clist, xtype='uint32_t'): 68 | print 'static {xtype} {name}({xtype} x) {{'.format(name=name, xtype=xtype) 69 | for c in clist: 70 | print '\t%s;' % op2code(c, xtype) 71 | print '\treturn x;\n}\n' 72 | 73 | def emit_c_obj(name, clist, xtype='uint32_t'): 74 | print 'struct %s : burt_hash {' % name 75 | print '\t{xtype} operator()({xtype} x) {{'.format(name=name, xtype=xtype) 76 | for c in clist: 77 | print '\t\t%s;' % op2code(c, xtype) 78 | print '\t\treturn x;\n\t}\n};\n' 79 | 80 | def emit_c_epilogue(nlists, name): 81 | print '{name}::function * {name}::select_hash(uint32_t selector) {{'.format(name=name); 82 | print '\tswitch(selector %% %d) {' % nlists 83 | print '\tdefault:' 84 | for i in range(nlists): 85 | print '\tcase {i}: return &hash{i};'.format(i=i) 86 | print '\t}\n}\n' 87 | 88 | def emit_c_prologue(nlists): 89 | print ''' 90 | /*************************************************** 91 | * * * * * * 92 | * * * * * * DO NOT MODIFY * * * * * * 93 | * * * * * * 94 | * * * Automatically generated by burt-hash.py * * * 95 | ****************************************************/ 96 | #include "burt-hash.h" 97 | 98 | ''' 99 | 100 | i=0 101 | lists = [clist.split() for clist in hash_constants.splitlines() if clist] 102 | 103 | #dbg = ['{%s}' % c for clist in lists for c in clist] 104 | #print ' '.join(dbg) 105 | 106 | # in hardware, limit the number of expensive add/sub we use 107 | addsub_limit = 5 108 | lists = [clist for clist in lists 109 | if sum(1 for c in clist if int(c) < 64) < addsub_limit] 110 | 111 | # emit the code 112 | emit_c_prologue(len(lists)) 113 | for i,clist in enumerate(lists): 114 | classes = [] 115 | for c in clist: 116 | c = int(c) 117 | if c < 32: 118 | classes.append(0) 119 | elif c < 64: 120 | classes.append(1) 121 | elif c < 96: 122 | classes.append(2) 123 | else: 124 | classes.append(3) 125 | 126 | emit_c('hash%d' % i, clist, 'uint32_t') 127 | emit_c('hash%d' % i, clist, '__v4si') 128 | 129 | # now the epilogue 130 | emit_c_epilogue(len(lists),'burt_hash') 131 | emit_c_epilogue(len(lists),'burt_hash4') 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PreemptDB: Low-Latency Transaction Scheduling via Userspace Interrupts 2 | 3 | PreemptDB a database engine that supports lightweight userspace preemptible transactions enabled by Intel x86 user interrupt (uintr). 4 | PreemptDB allows high-priority, short-transactions to quickly preempt and pause long-running, low-priority transactions which is resumed after the short-transaction concludes. 5 | 6 | Check out more details in our [SIGMOD 2025 paper](https://kaisonghuang.github.io/resources/preemptdb-preprint.pdf) (received *Best Paper Award*!). If you use our work, please cite: 7 | 8 | ``` 9 | Low-Latency Transaction Scheduling via Userspace Interrupts: Why Wait or Yield When You Can Preempt? 10 | Kaisong Huang, Jiatang Zhou, Zhuoyue Zhao, Dong Xie, Tianzheng Wang. 11 | SIGMOD 2025 12 | ``` 13 | 14 | ### Step 1: Check if User Interrupt is Supported 15 | Please build and run this [tool](https://github.com/UB-ADBLAB/check_uintr) to check if your CPU supports user interrupt. 16 | 17 | ### Step 2: Enable Kernel Support for User Interrupt 18 | We have two options to enable kernel support for user interrupts: 19 | 1. Patched Kernel: We provide a patched kernel with uintr support. You can download it from [here](https://github.com/UB-ADBLAB/ubuntu-linux-uintr). Follow the instructions in the repository to build and install the kernel. 20 | 2. Character Device: If you prefer not using a patched kernel, you can use an alternative character device interface from [here](https://github.com/UB-ADBLAB/uintr-driver). This allows you to enable uintr support without modifying the kernel. If your kernel already enables uintr, do not use the character device. To build the system with the alternative device driver, please add `-DUSE_LIBUINTRDRIV=ON` flag to the cmake command in step 4. 21 | 22 | 23 | ### Step 3: Allocate Huge Pages 24 | PreemptDB uses huge pages for memory allocation. You can allocate huge pages using the following command: 25 | ```bash 26 | sudo sysctl -w vm.nr_hugepages=[preferred number of huge pages] 27 | 28 | sudo sysctl -p 29 | ``` 30 | 31 | ### Step 4: Build PreemptDB 32 | ```bash 33 | git clone https://github.com/sfu-dis/preemptdb.git 34 | 35 | cd preemptdb 36 | 37 | mkdir build 38 | 39 | cd build 40 | 41 | # Default: Release, USE_LIBUINTRDRIV=OFF 42 | cmake .. \ 43 | -DCMAKE_BUILD_TYPE=[Debug|RelWithDebInfo|Release] \ 44 | -DUSE_LIBUINTRDRIV=[ON|OFF] 45 | 46 | make 47 | ``` 48 | 49 | ### Step 5: Run PreemptDB 50 | Before you run PreemptDB, make sure you have chosen the desired parameter values: 51 | - `--log_data_dir`: Directory for log data. Make sure the directory exists and is writable. 52 | - `--node_memory_gb`: Memory allocated for each node in GB. Make sure the total memory allocated does not exceed the available hugepage memory. 53 | - `--tpcc_scale_factor`: Scale factor for the TPC-C benchmark. This determines the size of the database. 54 | - `--tpcc_workload_mix`: [New-Order, Payment, Credit-Check, Delivery, Order-Status, Stock-Level, TPC-H Query 2 variant, unused profile]: TPC-C transaction profiles with additional analytical query profiles. It is the workload mix run in the default transaction context. We typically use 0,0,0,0,0,0,100,0 which means only long-running TPC-H Query 2 is run in the default transaction context. 55 | - `--tpcc_prioritized_workload_mix`: TPC-C transaction profiles with additional analytical query profiles. It is the workload mix run in the prioritized transaction context. We typically use 50,50,0,0,0,0,0,0 which means 50% TPC-C New-Order and 50% TPC-C Payment are run in the prioritized transaction context. 56 | - `--scheduling_policy`: 1: Vanilla (FIFO wait), 2: Preemptive (PreemptDB), 3: Cooperative (userspace transaction context switch but not coroutine-based). 57 | - `--prioritized_queue_size`: Size of the prioritized/preemptive transaction queue in each worker thread. 58 | - `--global_queue_size`: Size of the global preemptive transaction queue in the uintr sender (admission control) thread. 59 | - `--arrival_interval_us`: Arrival interval of preemptive transactions in microseconds. 60 | - `--max_preempted_cycle_pct`: Maximum percentage of cycles that can be preempted from the default transaction context. 61 | - `--latency_sample_size`: Number of latency samples to collect for each run. 62 | ```bash 63 | mkdir /home/$USER/preemptdb-log 64 | 65 | cd build 66 | 67 | ./benchmarks/tpcc/tpcc_SI_sequential \ 68 | --log_data_dir=/home/$USER/preemptdb-log \ 69 | --null_log_device=1 \ 70 | --pcommit=0 \ 71 | --node_memory_gb=64 \ 72 | --tpcc_scale_factor=8 \ 73 | --tpcc_workload_mix=0,0,0,0,0,0,100,0 \ 74 | --tpcc_prioritized_workload_mix=50,50,0,0,0,0,0,0 \ 75 | --scheduling_policy=2 \ 76 | --prioritized_queue_size=8 \ 77 | --global_queue_size=64 \ 78 | --arrival_interval_us=1000 \ 79 | --max_preempted_cycle_pct=100 \ 80 | --latency_sample_size=1000 \ 81 | --seconds=30 \ 82 | --threads=8 83 | ``` 84 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/template_util_unittest.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2005 Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // ---- 31 | // 32 | // These tests are really compile time tests. 33 | // If you try to step through this in a debugger 34 | // you will not see any evaluations, merely that 35 | // value is assigned true or false sequentially. 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | #include "testutil.h" 42 | 43 | using namespace GOOGLE_NAMESPACE; 44 | 45 | namespace { 46 | 47 | TEST(TemplateUtilTest, TestSize) { 48 | EXPECT_GT(sizeof(GOOGLE_NAMESPACE::big_), sizeof(GOOGLE_NAMESPACE::small_)); 49 | } 50 | 51 | TEST(TemplateUtilTest, TestIntegralConstants) { 52 | // test the built-in types. 53 | EXPECT_TRUE(true_type::value); 54 | EXPECT_FALSE(false_type::value); 55 | 56 | typedef integral_constant one_type; 57 | EXPECT_EQ(1, one_type::value); 58 | } 59 | 60 | TEST(TemplateUtilTest, TestTemplateIf) { 61 | typedef if_::type if_true; 62 | EXPECT_TRUE(if_true::value); 63 | 64 | typedef if_::type if_false; 65 | EXPECT_FALSE(if_false::value); 66 | } 67 | 68 | TEST(TemplateUtilTest, TestTemplateTypeEquals) { 69 | // Check that the TemplateTypeEquals works correctly. 70 | bool value = false; 71 | 72 | // Test the same type is true. 73 | value = type_equals_::value; 74 | EXPECT_TRUE(value); 75 | 76 | // Test different types are false. 77 | value = type_equals_::value; 78 | EXPECT_FALSE(value); 79 | 80 | // Test type aliasing. 81 | typedef const int foo; 82 | value = type_equals_::value; 83 | EXPECT_TRUE(value); 84 | } 85 | 86 | TEST(TemplateUtilTest, TestTemplateAndOr) { 87 | // Check that the TemplateTypeEquals works correctly. 88 | bool value = false; 89 | 90 | // Yes && Yes == true. 91 | value = and_::value; 92 | EXPECT_TRUE(value); 93 | // Yes && No == false. 94 | value = and_::value; 95 | EXPECT_FALSE(value); 96 | // No && Yes == false. 97 | value = and_::value; 98 | EXPECT_FALSE(value); 99 | // No && No == false. 100 | value = and_::value; 101 | EXPECT_FALSE(value); 102 | 103 | // Yes || Yes == true. 104 | value = or_::value; 105 | EXPECT_TRUE(value); 106 | // Yes || No == true. 107 | value = or_::value; 108 | EXPECT_TRUE(value); 109 | // No || Yes == true. 110 | value = or_::value; 111 | EXPECT_TRUE(value); 112 | // No || No == false. 113 | value = or_::value; 114 | EXPECT_FALSE(value); 115 | } 116 | 117 | TEST(TemplateUtilTest, TestIdentity) { 118 | EXPECT_TRUE( 119 | (type_equals_::type, int>::value)); 120 | EXPECT_TRUE( 121 | (type_equals_::type, void>::value)); 122 | } 123 | 124 | } // namespace 125 | 126 | #include 127 | 128 | int main(int, char **) { 129 | // All the work is done in the static constructors. If they don't 130 | // die, the tests have all passed. 131 | std::cout << "PASS\n"; 132 | return 0; 133 | } 134 | 135 | -------------------------------------------------------------------------------- /dbcore/tests/w_rand.cpp: -------------------------------------------------------------------------------- 1 | /* -*- mode:C++; c-basic-offset:4 -*- 2 | Shore-MT -- Multi-threaded port of the SHORE storage manager 3 | 4 | Copyright (c) 2013 5 | 6 | Department of Computer Science 7 | University of Toronto 8 | 9 | All Rights Reserved. 10 | 11 | Permission to use, copy, modify and distribute this software and 12 | its documentation is hereby granted, provided that both the 13 | copyright notice and this permission notice appear in all copies of 14 | the software, derivative works or modified versions, and any 15 | portions thereof, and that both notices appear in supporting 16 | documentation. 17 | 18 | This code is distributed in the hope that it will be useful, but 19 | WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS 21 | DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER 22 | RESULTING FROM THE USE OF THIS SOFTWARE. 23 | */ 24 | #include "w_rand.h" 25 | #include "stopwatch.h" 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | w_rand::w_rand() : _state(0) { 32 | uint64_t now = stopwatch_t::now(); 33 | uint32_t s[] = { 34 | (uint32_t)(uintptr_t)&_state, (uint32_t)getpid(), 35 | (uint32_t)(uintptr_t)pthread_self(), (uint32_t)now, (uint32_t)(now >> 32), 36 | }; 37 | seed(s); 38 | } 39 | 40 | void w_rand::seed(uint32_t const *w, size_t n) { 41 | for (size_t j = 0; n and j < R; j++) _arr[(R - j) & 0xf] = w[(j % n)]; 42 | 43 | // warm up the internal state to ensure high quality output 44 | for (int i = 0; i < 100; i++) rand(); 45 | } 46 | 47 | /* Select an unsigned 32-bit integer uniformly and at random. 48 | */ 49 | uint32_t w_rand::rand() { 50 | uint32_t si = _state; 51 | uint32_t si7 = (si + 7) & 0xf; 52 | uint32_t si3 = (si + 3) & 0xf; 53 | uint32_t si1 = (si + 1) & 0xf; 54 | 55 | uint32_t v0 = _arr[si]; 56 | uint32_t v7 = _arr[si7]; 57 | uint32_t v3 = _arr[si3]; 58 | uint32_t z0 = _arr[si1]; 59 | 60 | uint32_t z1 = v0 ^ (v0 << 16) ^ v3 ^ (v3 << 15); 61 | uint32_t z2 = v7 ^ (v7 >> 11); 62 | uint32_t z3 = z1 ^ z2; 63 | uint32_t z4 = 64 | z0 ^ (z0 << 2) ^ (z1 << 18) ^ z2 ^ (z2 << 28) ^ ((z3 & 0x6d22169) << 5); 65 | 66 | _arr[si] = z3; 67 | _arr[si1] = z4; 68 | _state = si1; 69 | return z4; 70 | } 71 | 72 | /* Select an integer uniformly and at random from the range 0 <= x 73 | < @end, where @end is a 32-bit unsigned integer. 74 | */ 75 | uint32_t w_rand::randn(uint32_t end) { 76 | if (end < 2) return 0; 77 | 78 | uint32_t rval; 79 | do { 80 | rval = uint64_t(end) * rand() / ~uint32_t(0); 81 | } while (rval >= end); 82 | return rval; 83 | } 84 | 85 | uint32_t w_rand::randn(uint32_t a, uint32_t b) { 86 | if (b < a) { 87 | using std::swap; 88 | swap(a, b); 89 | } 90 | 91 | return a + randn(b - a + 1); 92 | } 93 | 94 | /* Generate a floating point value in the range 0 <= x < 1, with 95 | 32 bits of precision (this is a 32-bit RNG, after all). 96 | 97 | To minimize the cost of converting a 32-bit int to double, we 98 | assemble a double directly, using the IEEE 754 specification: 99 | 100 | |S|EEEEEEEEEEE|FFFFFF....F| 101 | (11 bits) (52 bits) 102 | 103 | The value is then (-1)**S * 2**(E-1023) * 1.F; in other words, 104 | F is the fractional part of an implied 53-bit fixed-point 105 | number that ranges from 1.000... to 1.111...). 106 | 107 | In our case, we let F = 1.00000xxxxxxxx (in hex notation), with 108 | S=0 and an exponent of 20 (E=1043), which yields the normalized 109 | equivalent of 100000.xxxxxxxx. From there, we simply subtract 110 | 0x100000 to recover the number we actually want (0.xxxxxxxx). 111 | 112 | The compiler optimizes the below into a logical OR, two 113 | constant loads, and one floating point subtract. The latter 114 | lets us avoid a 20-bit shift and also takes care of 115 | normalization. 116 | */ 117 | double w_rand::drand() { 118 | uint64_t bits = 20; 119 | union { 120 | uint64_t n; 121 | double d; 122 | } u = {((1023 + bits) << 52) | rand()}; 123 | return u.d - double(1 << bits); 124 | } 125 | 126 | #ifdef TEST_W_RAND 127 | #include 128 | 129 | void __attribute__((noinline)) once(w_rand &rng) { rng.rand(); } 130 | 131 | int main() { 132 | w_rand rng; 133 | for (int i = 0; i < 16; i++) { 134 | for (int j = 0; j < 8; j++) printf("%08x ", rng.rand()); 135 | printf("\n"); 136 | } 137 | 138 | printf("\n"); 139 | for (int j = 0; j < 20; j++) { 140 | for (int i = 0; i < 40; i++) printf("%d ", rng.randn(10)); 141 | printf("\n"); 142 | } 143 | 144 | printf("\n"); 145 | for (int j = 0; j < 20; j++) { 146 | for (int i = 0; i < 10; i++) printf("%.5f ", rng.drand()); 147 | printf("\n"); 148 | } 149 | 150 | for (int i = 0; i < 1e9; i++) once(rng); 151 | } 152 | #endif 153 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/windows/config.h: -------------------------------------------------------------------------------- 1 | #ifndef GOOGLE_SPARSEHASH_WINDOWS_CONFIG_H_ 2 | #define GOOGLE_SPARSEHASH_WINDOWS_CONFIG_H_ 3 | 4 | /* src/config.h.in. Generated from configure.ac by autoheader. */ 5 | 6 | /* Namespace for Google classes */ 7 | #define GOOGLE_NAMESPACE ::google 8 | 9 | /* the location of the header defining hash functions */ 10 | #define HASH_FUN_H 11 | 12 | /* the location of or */ 13 | #define HASH_MAP_H 14 | 15 | /* the namespace of the hash<> function */ 16 | #define HASH_NAMESPACE stdext 17 | 18 | /* the location of or */ 19 | #define HASH_SET_H 20 | 21 | /* Define to 1 if you have the header file. */ 22 | #undef HAVE_GOOGLE_MALLOC_EXTENSION_H 23 | 24 | /* define if the compiler has hash_map */ 25 | #define HAVE_HASH_MAP 1 26 | 27 | /* define if the compiler has hash_set */ 28 | #define HAVE_HASH_SET 1 29 | 30 | /* Define to 1 if you have the header file. */ 31 | #undef HAVE_INTTYPES_H 32 | 33 | /* Define to 1 if the system has the type `long long'. */ 34 | #define HAVE_LONG_LONG 1 35 | 36 | /* Define to 1 if you have the `memcpy' function. */ 37 | #define HAVE_MEMCPY 1 38 | 39 | /* Define to 1 if you have the `memmove' function. */ 40 | #define HAVE_MEMMOVE 1 41 | 42 | /* Define to 1 if you have the header file. */ 43 | #undef HAVE_MEMORY_H 44 | 45 | /* define if the compiler implements namespaces */ 46 | #define HAVE_NAMESPACES 1 47 | 48 | /* Define if you have POSIX threads libraries and header files. */ 49 | #undef HAVE_PTHREAD 50 | 51 | /* Define to 1 if you have the header file. */ 52 | #undef HAVE_STDINT_H 53 | 54 | /* Define to 1 if you have the header file. */ 55 | #define HAVE_STDLIB_H 1 56 | 57 | /* Define to 1 if you have the header file. */ 58 | #undef HAVE_STRINGS_H 59 | 60 | /* Define to 1 if you have the header file. */ 61 | #define HAVE_STRING_H 1 62 | 63 | /* Define to 1 if you have the header file. */ 64 | #undef HAVE_SYS_RESOURCE_H 65 | 66 | /* Define to 1 if you have the header file. */ 67 | #define HAVE_SYS_STAT_H 1 68 | 69 | /* Define to 1 if you have the header file. */ 70 | #undef HAVE_SYS_TIME_H 71 | 72 | /* Define to 1 if you have the header file. */ 73 | #define HAVE_SYS_TYPES_H 1 74 | 75 | /* Define to 1 if you have the header file. */ 76 | #undef HAVE_SYS_UTSNAME_H 77 | 78 | /* Define to 1 if the system has the type `uint16_t'. */ 79 | #undef HAVE_UINT16_T 80 | 81 | /* Define to 1 if you have the header file. */ 82 | #undef HAVE_UNISTD_H 83 | 84 | /* define if the compiler supports unordered_{map,set} */ 85 | #undef HAVE_UNORDERED_MAP 86 | 87 | /* Define to 1 if the system has the type `u_int16_t'. */ 88 | #undef HAVE_U_INT16_T 89 | 90 | /* Define to 1 if the system has the type `__uint16'. */ 91 | #define HAVE___UINT16 1 92 | 93 | /* Name of package */ 94 | #undef PACKAGE 95 | 96 | /* Define to the address where bug reports for this package should be sent. */ 97 | #undef PACKAGE_BUGREPORT 98 | 99 | /* Define to the full name of this package. */ 100 | #undef PACKAGE_NAME 101 | 102 | /* Define to the full name and version of this package. */ 103 | #undef PACKAGE_STRING 104 | 105 | /* Define to the one symbol short name of this package. */ 106 | #undef PACKAGE_TARNAME 107 | 108 | /* Define to the home page for this package. */ 109 | #undef PACKAGE_URL 110 | 111 | /* Define to the version of this package. */ 112 | #undef PACKAGE_VERSION 113 | 114 | /* Define to necessary symbol if this constant uses a non-standard name on 115 | your system. */ 116 | #undef PTHREAD_CREATE_JOINABLE 117 | 118 | /* The system-provided hash function including the namespace. */ 119 | #define SPARSEHASH_HASH HASH_NAMESPACE::hash_compare 120 | 121 | /* The system-provided hash function, in namespace HASH_NAMESPACE. */ 122 | #define SPARSEHASH_HASH_NO_NAMESPACE hash_compare 123 | 124 | /* Define to 1 if you have the ANSI C header files. */ 125 | #define STDC_HEADERS 1 126 | 127 | /* Version number of package */ 128 | #undef VERSION 129 | 130 | /* Stops putting the code inside the Google namespace */ 131 | #define _END_GOOGLE_NAMESPACE_ } 132 | 133 | /* Puts following code inside the Google namespace */ 134 | #define _START_GOOGLE_NAMESPACE_ namespace google { 135 | 136 | 137 | // --------------------------------------------------------------------- 138 | // Extra stuff not found in config.h.in 139 | 140 | #define HAVE_WINDOWS_H 1 // used in time_hash_map 141 | 142 | // This makes sure the definitions in config.h and sparseconfig.h match 143 | // up. If they don't, the compiler will complain about redefinition. 144 | #include 145 | 146 | // TODO(csilvers): include windows/port.h in every relevant source file instead? 147 | #include "windows/port.h" 148 | 149 | #endif /* GOOGLE_SPARSEHASH_WINDOWS_CONFIG_H_ */ 150 | -------------------------------------------------------------------------------- /third-party/sparsehash/src/libc_allocator_with_realloc_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2010, Google Inc. 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without 5 | // modification, are permitted provided that the following conditions are 6 | // met: 7 | // 8 | // * Redistributions of source code must retain the above copyright 9 | // notice, this list of conditions and the following disclaimer. 10 | // * Redistributions in binary form must reproduce the above 11 | // copyright notice, this list of conditions and the following disclaimer 12 | // in the documentation and/or other materials provided with the 13 | // distribution. 14 | // * Neither the name of Google Inc. nor the names of its 15 | // contributors may be used to endorse or promote products derived from 16 | // this software without specific prior written permission. 17 | // 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | // --- 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "testutil.h" 40 | 41 | using std::cerr; 42 | using std::cout; 43 | using std::string; 44 | using std::basic_string; 45 | using std::char_traits; 46 | using std::vector; 47 | using GOOGLE_NAMESPACE::libc_allocator_with_realloc; 48 | 49 | #define arraysize(a) ( sizeof(a) / sizeof(*(a)) ) 50 | 51 | namespace { 52 | 53 | typedef libc_allocator_with_realloc int_alloc; 54 | typedef int_alloc::rebind::other intp_alloc; 55 | 56 | // cstring allocates from libc_allocator_with_realloc. 57 | typedef basic_string, 58 | libc_allocator_with_realloc > cstring; 59 | typedef vector > cstring_vector; 60 | 61 | TEST(LibcAllocatorWithReallocTest, Allocate) { 62 | int_alloc alloc; 63 | intp_alloc palloc; 64 | 65 | int** parray = palloc.allocate(1024); 66 | for (int i = 0; i < 16; ++i) { 67 | parray[i] = alloc.allocate(i * 1024 + 1); 68 | } 69 | for (int i = 0; i < 16; ++i) { 70 | alloc.deallocate(parray[i], i * 1024 + 1); 71 | } 72 | palloc.deallocate(parray, 1024); 73 | 74 | int* p = alloc.allocate(4096); 75 | p[0] = 1; 76 | p[1023] = 2; 77 | p[4095] = 3; 78 | p = alloc.reallocate(p, 8192); 79 | EXPECT_EQ(1, p[0]); 80 | EXPECT_EQ(2, p[1023]); 81 | EXPECT_EQ(3, p[4095]); 82 | p = alloc.reallocate(p, 1024); 83 | EXPECT_EQ(1, p[0]); 84 | EXPECT_EQ(2, p[1023]); 85 | alloc.deallocate(p, 1024); 86 | } 87 | 88 | TEST(LibcAllocatorWithReallocTest, TestSTL) { 89 | // Test strings copied from base/arena_unittest.cc 90 | static const char* test_strings[] = { 91 | "aback", "abaft", "abandon", "abandoned", "abandoning", 92 | "abandonment", "abandons", "abase", "abased", "abasement", 93 | "abasements", "abases", "abash", "abashed", "abashes", "abashing", 94 | "abasing", "abate", "abated", "abatement", "abatements", "abater", 95 | "abates", "abating", "abbe", "abbey", "abbeys", "abbot", "abbots", 96 | "abbreviate", "abbreviated", "abbreviates", "abbreviating", 97 | "abbreviation", "abbreviations", "abdomen", "abdomens", "abdominal", 98 | "abduct", "abducted", "abduction", "abductions", "abductor", "abductors", 99 | "abducts", "Abe", "abed", "Abel", "Abelian", "Abelson", "Aberdeen", 100 | "Abernathy", "aberrant", "aberration", "aberrations", "abet", "abets", 101 | "abetted", "abetter", "abetting", "abeyance", "abhor", "abhorred", 102 | "abhorrent", "abhorrer", "abhorring", "abhors", "abide", "abided", 103 | "abides", "abiding"}; 104 | cstring_vector v; 105 | for (size_t i = 0; i < arraysize(test_strings); ++i) { 106 | v.push_back(test_strings[i]); 107 | } 108 | for (size_t i = arraysize(test_strings); i > 0; --i) { 109 | EXPECT_EQ(cstring(test_strings[i-1]), v.back()); 110 | v.pop_back(); 111 | } 112 | } 113 | 114 | } // namespace 115 | 116 | int main(int, char **) { 117 | // All the work is done in the static constructors. If they don't 118 | // die, the tests have all passed. 119 | cout << "PASS\n"; 120 | return 0; 121 | } 122 | 123 | --------------------------------------------------------------------------------