├── .gitignore ├── LICENSE ├── Makefile.in ├── README.md ├── aclocal.m4 ├── build-aux ├── install-sh └── m4 │ ├── ax_check_compile_flag.m4 │ ├── ax_cxx_compile_stdcxx.m4 │ ├── ax_cxx_compile_stdcxx_0x.m4 │ ├── ax_cxx_compile_stdcxx_11.m4 │ ├── ax_cxx_compile_stdcxx_14.m4 │ ├── ax_cxx_compile_stdcxx_17.m4 │ ├── ax_lib_sqlite3.m4 │ ├── ax_openmp.m4 │ ├── ax_subdirs_configure.m4 │ ├── my_arg_enable.m4 │ ├── my_check_stdlib_libcxx.m4 │ └── my_set_cc_flag.m4 ├── configure.ac ├── include ├── teseo.hpp └── teseo │ ├── aux │ ├── builder.hpp │ ├── cache.hpp │ ├── cb_serialise_build.hpp │ ├── counting_tree.hpp │ ├── dynamic_view.hpp │ ├── item.hpp │ ├── partial_result.hpp │ ├── static_view.hpp │ └── view.hpp │ ├── context │ ├── global_context.hpp │ ├── property_snapshot.hpp │ ├── scoped_epoch.hpp │ ├── static_configuration.hpp.in │ ├── tc_list.hpp │ └── thread_context.hpp │ ├── gc │ ├── garbage_collector.hpp │ ├── item.hpp │ ├── simple_queue.hpp │ └── tc_queue.hpp │ ├── interface │ └── iterator.hpp │ ├── memstore │ ├── context.hpp │ ├── cursor_state.hpp │ ├── data_item.hpp │ ├── dense_file.hpp │ ├── direct_pointer.hpp │ ├── error.hpp │ ├── index.hpp │ ├── index_entry.hpp │ ├── key.hpp │ ├── latch_state.hpp │ ├── leaf.hpp │ ├── memstore.hpp │ ├── remove_vertex.hpp │ ├── scan.hpp │ ├── segment.hpp │ ├── sparse_file.hpp │ ├── update.hpp │ ├── vertex_table.hpp │ └── wake_list.hpp │ ├── profiler │ ├── direct_access.hpp │ ├── event_global.hpp │ ├── event_list.hpp │ ├── event_name.hpp │ ├── event_thread.hpp │ ├── rebal_global_list.hpp │ ├── rebal_list.hpp │ ├── rebal_profiler.hpp │ ├── rebal_stats.hpp │ ├── rebal_time_unit.hpp │ ├── rebal_timer.hpp │ ├── save_to_disk.hpp │ └── scoped_timer.hpp │ ├── rebalance │ ├── crawler.hpp │ ├── merge_operator.hpp │ ├── merger_service.hpp │ ├── plan.hpp │ ├── rebalance.hpp │ ├── rebalanced_leaf.hpp │ ├── scratchpad.hpp │ ├── spread_operator.hpp │ └── weighted_edge.hpp │ ├── runtime │ ├── queue.hpp │ ├── runtime.hpp │ ├── task.hpp │ ├── timer_service.hpp │ └── worker.hpp │ ├── third-party │ └── magic_enum.hpp │ ├── transaction │ ├── memory_pool.hpp │ ├── memory_pool_list.hpp │ ├── rollback_interface.hpp │ ├── transaction_impl.hpp │ ├── transaction_iterator.hpp │ ├── transaction_latch.hpp │ ├── transaction_list.hpp │ ├── transaction_sequence.hpp │ ├── undo.hpp │ └── undo_buffer.hpp │ └── util │ ├── abtree.hpp │ ├── assembly.hpp │ ├── bitset.hpp │ ├── chrono.hpp │ ├── circular_array.hpp │ ├── circular_array_64k.hpp │ ├── compiler.hpp │ ├── cpu_topology.hpp │ ├── debug.hpp │ ├── error.hpp │ ├── interface.hpp │ ├── latch.hpp │ ├── libevent.hpp │ ├── numa.hpp │ ├── permutation.hpp │ ├── system.hpp │ ├── thread.hpp │ ├── timer.hpp │ └── tournament_tree.hpp ├── src ├── aux │ ├── builder.cpp │ ├── cache.cpp │ ├── cb_serialise_build.cpp │ ├── counting_tree.cpp │ ├── dynamic_view.cpp │ ├── item.cpp │ ├── partial_result.cpp │ ├── static_view.cpp │ └── view.cpp ├── context │ ├── global_context.cpp │ ├── property_snapshot.cpp │ ├── tc_list.cpp │ └── thread_context.cpp ├── gc │ ├── garbage_collector.cpp │ ├── item.cpp │ ├── simple_queue.cpp │ └── tc_queue.cpp ├── memstore │ ├── context.cpp │ ├── cursor_state.cpp │ ├── data_item.cpp │ ├── dense_file.cpp │ ├── direct_pointer.cpp │ ├── index.cpp │ ├── latch_state.cpp │ ├── leaf.cpp │ ├── memstore.cpp │ ├── remove_vertex.cpp │ ├── segment.cpp │ ├── sparse_file.cpp │ ├── update.cpp │ ├── vertex_table.cpp │ └── wake_list.cpp ├── profiler │ ├── direct_access.cpp │ ├── event_global.cpp │ ├── event_thread.cpp │ ├── rebal_global_list.cpp │ ├── rebal_list.cpp │ ├── rebal_profiler.cpp │ ├── rebal_stats.cpp │ ├── save_to_disk.cpp │ └── scoped_timer.cpp ├── rebalance │ ├── crawler.cpp │ ├── merge_operator.cpp │ ├── merger_service.cpp │ ├── plan.cpp │ ├── rebalance.cpp │ ├── rebalanced_leaf.cpp │ ├── scratchpad.cpp │ ├── spread_operator.cpp │ └── weighted_edge.cpp ├── runtime │ ├── queue.cpp │ ├── runtime.cpp │ ├── task.cpp │ ├── timer_service.cpp │ └── worker.cpp ├── teseo.cpp ├── transaction │ ├── memory_pool.cpp │ ├── memory_pool_list.cpp │ ├── rollback_interface.cpp │ ├── transaction_impl.cpp │ ├── transaction_list.cpp │ ├── transaction_sequence.cpp │ ├── undo.cpp │ └── undo_buffer.cpp └── util │ ├── chrono.cpp │ ├── cpu_topology.cpp │ ├── debug.cpp │ ├── error.cpp │ ├── interface.cpp │ ├── libevent.cpp │ ├── numa.cpp │ ├── system.cpp │ ├── thread.cpp │ └── timer.cpp └── tests ├── catch.cpp ├── catch.hpp ├── test_aux_view.cpp ├── test_circular_array.cpp ├── test_context.cpp ├── test_cursor_state.cpp ├── test_degree.cpp ├── test_dense_file.cpp ├── test_index.cpp ├── test_index_data.hpp ├── test_iterator.cpp ├── test_latch.cpp ├── test_memstore.cpp ├── test_merger.cpp ├── test_numa.cpp ├── test_parallel.cpp ├── test_rebalance.cpp ├── test_segment.cpp ├── test_sparse_file.cpp ├── test_tcqueue.cpp ├── test_tournament_tree.cpp ├── test_transaction_impl.cpp ├── test_transaction_pool.cpp ├── test_transaction_prune.cpp └── test_vertex_table.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Project files 2 | /.cproject 3 | /.project 4 | /.settings/ 5 | 6 | # Autoconf 7 | /autom4te.cache/ 8 | /configure 9 | 10 | # Builds 11 | /build/ 12 | /Debug/ 13 | /Release/ 14 | -------------------------------------------------------------------------------- /aclocal.m4: -------------------------------------------------------------------------------- 1 | ############################################################################# 2 | # Include all m4 files from ./build-aux/m4 3 | m4_pushdef([DIR_BUNDLE_M4], [[build-aux/m4]]) 4 | m4_foreach_w([i], m4_esyscmd_s([ls ']DIR_BUNDLE_M4[' | egrep '*.m4$']), [m4_include(DIR_BUNDLE_M4/i)]) 5 | m4_popdef([DIR_BUNDLE_M4]) -------------------------------------------------------------------------------- /build-aux/m4/ax_check_compile_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the current language's compiler 12 | # or gives an error. (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the current language's default 18 | # flags (e.g. CFLAGS) when the check is done. The check is thus made with 19 | # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to 20 | # force the compiler to issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_COMPILE_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # This program is free software: you can redistribute it and/or modify it 33 | # under the terms of the GNU General Public License as published by the 34 | # Free Software Foundation, either version 3 of the License, or (at your 35 | # option) any later version. 36 | # 37 | # This program is distributed in the hope that it will be useful, but 38 | # WITHOUT ANY WARRANTY; without even the implied warranty of 39 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 40 | # Public License for more details. 41 | # 42 | # You should have received a copy of the GNU General Public License along 43 | # with this program. If not, see . 44 | # 45 | # As a special exception, the respective Autoconf Macro's copyright owner 46 | # gives unlimited permission to copy, distribute and modify the configure 47 | # scripts that are the output of Autoconf when processing the Macro. You 48 | # need not follow the terms of the GNU General Public License when using 49 | # or distributing such scripts, even though portions of the text of the 50 | # Macro appear in them. The GNU General Public License (GPL) does govern 51 | # all other use of the material that constitutes the Autoconf Macro. 52 | # 53 | # This special exception to the GPL applies to versions of the Autoconf 54 | # Macro released by the Autoconf Archive. When you make and distribute a 55 | # modified version of the Autoconf Macro, you may extend this special 56 | # exception to the GPL to apply to your modified version as well. 57 | 58 | #serial 5 59 | 60 | AC_DEFUN([AX_CHECK_COMPILE_FLAG], 61 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 62 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl 63 | AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ 64 | ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS 65 | _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" 66 | AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 67 | [AS_VAR_SET(CACHEVAR,[yes])], 68 | [AS_VAR_SET(CACHEVAR,[no])]) 69 | _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) 70 | AS_VAR_IF(CACHEVAR,yes, 71 | [m4_default([$2], :)], 72 | [m4_default([$3], :)]) 73 | AS_VAR_POPDEF([CACHEVAR])dnl 74 | ])dnl AX_CHECK_COMPILE_FLAGS 75 | -------------------------------------------------------------------------------- /build-aux/m4/ax_cxx_compile_stdcxx_0x.m4: -------------------------------------------------------------------------------- 1 | # ============================================================================= 2 | # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_0x.html 3 | # ============================================================================= 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CXX_COMPILE_STDCXX_0X 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check for baseline language coverage in the compiler for the C++0x 12 | # standard. 13 | # 14 | # This macro is deprecated and has been superseded by the 15 | # AX_CXX_COMPILE_STDCXX_11 macro which should be used instead. 16 | # 17 | # LICENSE 18 | # 19 | # Copyright (c) 2008 Benjamin Kosnik 20 | # 21 | # Copying and distribution of this file, with or without modification, are 22 | # permitted in any medium without royalty provided the copyright notice 23 | # and this notice are preserved. This file is offered as-is, without any 24 | # warranty. 25 | 26 | #serial 12 27 | 28 | AU_ALIAS([AC_CXX_COMPILE_STDCXX_0X], [AX_CXX_COMPILE_STDCXX_0X]) 29 | AC_DEFUN([AX_CXX_COMPILE_STDCXX_0X], [ 30 | AC_OBSOLETE([$0], [; use AX_CXX_COMPILE_STDCXX_11 instead]) 31 | AC_CACHE_CHECK(if g++ supports C++0x features without additional flags, 32 | ax_cv_cxx_compile_cxx0x_native, 33 | [AC_LANG_PUSH([C++]) 34 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 35 | template 36 | struct check 37 | { 38 | static_assert(sizeof(int) <= sizeof(T), "not big enough"); 39 | }; 40 | 41 | typedef check> right_angle_brackets; 42 | 43 | int a; 44 | decltype(a) b; 45 | 46 | typedef check check_type; 47 | check_type c; 48 | check_type&& cr = static_cast(c);]], [])], 49 | [ax_cv_cxx_compile_cxx0x_native=yes], [ax_cv_cxx_compile_cxx0x_native=no]) 50 | AC_LANG_POP([C++]) 51 | ]) 52 | 53 | AC_CACHE_CHECK(if g++ supports C++0x features with -std=c++0x, 54 | ax_cv_cxx_compile_cxx0x_cxx, 55 | [AC_LANG_PUSH([C++]) 56 | ac_save_CXX="$CXX" 57 | CXX="$CXX -std=c++0x" 58 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 59 | template 60 | struct check 61 | { 62 | static_assert(sizeof(int) <= sizeof(T), "not big enough"); 63 | }; 64 | 65 | typedef check> right_angle_brackets; 66 | 67 | int a; 68 | decltype(a) b; 69 | 70 | typedef check check_type; 71 | check_type c; 72 | check_type&& cr = static_cast(c);]], [])], 73 | [ax_cv_cxx_compile_cxx0x_cxx=yes], [ax_cv_cxx_compile_cxx0x_cxx=no]) 74 | CXX="$ac_save_CXX" 75 | AC_LANG_POP([C++]) 76 | ]) 77 | 78 | AC_CACHE_CHECK(if g++ supports C++0x features with -std=gnu++0x, 79 | ax_cv_cxx_compile_cxx0x_gxx, 80 | [AC_LANG_PUSH([C++]) 81 | ac_save_CXX="$CXX" 82 | CXX="$CXX -std=gnu++0x" 83 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 84 | template 85 | struct check 86 | { 87 | static_assert(sizeof(int) <= sizeof(T), "not big enough"); 88 | }; 89 | 90 | typedef check> right_angle_brackets; 91 | 92 | int a; 93 | decltype(a) b; 94 | 95 | typedef check check_type; 96 | check_type c; 97 | check_type&& cr = static_cast(c);]], [])], 98 | [ax_cv_cxx_compile_cxx0x_gxx=yes], [ax_cv_cxx_compile_cxx0x_gxx=no]) 99 | CXX="$ac_save_CXX" 100 | AC_LANG_POP([C++]) 101 | ]) 102 | 103 | if test "$ax_cv_cxx_compile_cxx0x_native" = yes || 104 | test "$ax_cv_cxx_compile_cxx0x_cxx" = yes || 105 | test "$ax_cv_cxx_compile_cxx0x_gxx" = yes; then 106 | AC_DEFINE(HAVE_STDCXX_0X,,[Define if g++ supports C++0x features. ]) 107 | fi 108 | ]) 109 | -------------------------------------------------------------------------------- /build-aux/m4/ax_cxx_compile_stdcxx_11.m4: -------------------------------------------------------------------------------- 1 | # ============================================================================= 2 | # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html 3 | # ============================================================================= 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CXX_COMPILE_STDCXX_11([ext|noext], [mandatory|optional]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check for baseline language coverage in the compiler for the C++11 12 | # standard; if necessary, add switches to CXX and CXXCPP to enable 13 | # support. 14 | # 15 | # This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX 16 | # macro with the version set to C++11. The two optional arguments are 17 | # forwarded literally as the second and third argument respectively. 18 | # Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for 19 | # more information. If you want to use this macro, you also need to 20 | # download the ax_cxx_compile_stdcxx.m4 file. 21 | # 22 | # LICENSE 23 | # 24 | # Copyright (c) 2008 Benjamin Kosnik 25 | # Copyright (c) 2012 Zack Weinberg 26 | # Copyright (c) 2013 Roy Stogner 27 | # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov 28 | # Copyright (c) 2015 Paul Norman 29 | # Copyright (c) 2015 Moritz Klammler 30 | # 31 | # Copying and distribution of this file, with or without modification, are 32 | # permitted in any medium without royalty provided the copyright notice 33 | # and this notice are preserved. This file is offered as-is, without any 34 | # warranty. 35 | 36 | #serial 18 37 | 38 | AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX]) 39 | AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [AX_CXX_COMPILE_STDCXX([11], [$1], [$2])]) 40 | -------------------------------------------------------------------------------- /build-aux/m4/ax_cxx_compile_stdcxx_14.m4: -------------------------------------------------------------------------------- 1 | # ============================================================================= 2 | # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_14.html 3 | # ============================================================================= 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CXX_COMPILE_STDCXX_14([ext|noext], [mandatory|optional]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check for baseline language coverage in the compiler for the C++14 12 | # standard; if necessary, add switches to CXX and CXXCPP to enable 13 | # support. 14 | # 15 | # This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX 16 | # macro with the version set to C++14. The two optional arguments are 17 | # forwarded literally as the second and third argument respectively. 18 | # Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for 19 | # more information. If you want to use this macro, you also need to 20 | # download the ax_cxx_compile_stdcxx.m4 file. 21 | # 22 | # LICENSE 23 | # 24 | # Copyright (c) 2015 Moritz Klammler 25 | # 26 | # Copying and distribution of this file, with or without modification, are 27 | # permitted in any medium without royalty provided the copyright notice 28 | # and this notice are preserved. This file is offered as-is, without any 29 | # warranty. 30 | 31 | #serial 5 32 | 33 | AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX]) 34 | AC_DEFUN([AX_CXX_COMPILE_STDCXX_14], [AX_CXX_COMPILE_STDCXX([14], [$1], [$2])]) 35 | -------------------------------------------------------------------------------- /build-aux/m4/ax_cxx_compile_stdcxx_17.m4: -------------------------------------------------------------------------------- 1 | # ============================================================================= 2 | # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_17.html 3 | # ============================================================================= 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CXX_COMPILE_STDCXX_17([ext|noext], [mandatory|optional]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check for baseline language coverage in the compiler for the C++17 12 | # standard; if necessary, add switches to CXX and CXXCPP to enable 13 | # support. 14 | # 15 | # This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX 16 | # macro with the version set to C++17. The two optional arguments are 17 | # forwarded literally as the second and third argument respectively. 18 | # Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for 19 | # more information. If you want to use this macro, you also need to 20 | # download the ax_cxx_compile_stdcxx.m4 file. 21 | # 22 | # LICENSE 23 | # 24 | # Copyright (c) 2015 Moritz Klammler 25 | # Copyright (c) 2016 Krzesimir Nowak 26 | # 27 | # Copying and distribution of this file, with or without modification, are 28 | # permitted in any medium without royalty provided the copyright notice 29 | # and this notice are preserved. This file is offered as-is, without any 30 | # warranty. 31 | 32 | #serial 2 33 | 34 | AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX]) 35 | AC_DEFUN([AX_CXX_COMPILE_STDCXX_17], [AX_CXX_COMPILE_STDCXX([17], [$1], [$2])]) 36 | -------------------------------------------------------------------------------- /build-aux/m4/my_arg_enable.m4: -------------------------------------------------------------------------------- 1 | # Commodity wrapper for AC_ARG_ENABLE to enable/disable options. 2 | # There should be no external macro dependencies. 3 | # serial 2 4 | 5 | # _MY_SHELL_TEST_NE(value) 6 | # ------------------------------------------- 7 | # 8 | # Wraps inside the shell construct `test x"<_MY_OPTION_CURRENT>" != x""' 9 | # It assumes the macro _MY_OPTION_CURRENT already exists 10 | AC_DEFUN([_MY_SHELL_TEST_NE], [[test x"]_MY_OPTION_CURRENT[" != x"$1"]]) 11 | 12 | # _MY_VALIDATE_OPTIONS(option_name, variable, list_options) 13 | # ------------------------------------------- 14 | # 15 | # Check whether contains one of the options of the value in 16 | # , otherwise it terminates raising an error. 17 | AC_DEFUN([_MY_VALIDATE_OPTIONS], [dnl 18 | m4_pushdef([_MY_OPTION_CURRENT], [[$2]])dnl 19 | if m4_map_sep([_MY_SHELL_TEST_NE], [ && ], m4_split([$3])); then 20 | AC_MSG_ERROR([invalid value for the parameter $1. Possible choices are: m4_map_sep([m4_echo], [, ], m4_split([$3])). Given value: '$2']) 21 | fi 22 | m4_popdef([_MY_OPTION_CURRENT])dnl 23 | ]) 24 | 25 | # MY_VALIDATE_OPTIONS(option_name, variable, list_options) 26 | # ------------------------------------------- 27 | # 28 | # Check whether contains one of the options of the value in 29 | # , otherwise it terminates raising an error. The test is 30 | # performed immediately after the command line argument have been parsed 31 | AC_DEFUN([MY_VALIDATE_OPTIONS], [dnl 32 | m4_divert_push([INIT_PREPARE])dnl 33 | _MY_VALIDATE_OPTIONS([$1], [$2], [$3])dnl 34 | m4_divert_pop([INIT_PREPARE])dnl 35 | ]) 36 | 37 | # _MY_PRINT_CHOICE(arg) 38 | # ------------------------------------------- 39 | # 40 | # Echo the given argument 41 | AC_DEFUN([_MY_PRINT_CHOICE], [$1]) 42 | 43 | # MY_ARG_ENABLE(option_name, help_description, list_options, default) 44 | # ------------------------------------------- 45 | # 46 | # Wrapper for AC_ARG_ENABLE. Advertises the option --enable- and validates 47 | # the input choice among the possibilities . If the user does not 48 | # provide any value, it sets enable_ to 49 | AC_DEFUN([MY_ARG_ENABLE], [dnl 50 | dnl Set the default value first 51 | m4_pushdef([enable_variable], [enable_]AS_TR_SH([$1])) 52 | m4_divert_push([DEFAULTS]) 53 | AS_VAR_SET([enable_variable], ["$4"]) 54 | m4_divert_pop([DEFAULTS]) 55 | m4_pushdef([_MY_POSSIBLE_CHOICES], [m4_map_sep([_MY_PRINT_CHOICE], [, ], m4_split([$3]))]) 56 | AC_ARG_ENABLE([$1], AS_HELP_STRING([--m4_if([$4], [yes], [disable], [enable])-$1], 57 | [$2. Possible choices are: _MY_POSSIBLE_CHOICES. @<:@Default: $4@:>@])) 58 | m4_popdef([_MY_POSSIBLE_CHOICES]) 59 | dnl Finally, validate the option given from the user 60 | MY_VALIDATE_OPTIONS([--enable-$1], ${enable_variable}, [$3]) 61 | m4_popdef([enable_variable]) 62 | ]) 63 | -------------------------------------------------------------------------------- /build-aux/m4/my_check_stdlib_libcxx.m4: -------------------------------------------------------------------------------- 1 | # Check whether the option -stdlib=libc++ is available and the program 2 | # can be compiled, linked and executed. 3 | # libc++ is the STL replacement from the LLVM community: 4 | # https://libcxx.llvm.org/ 5 | # 6 | # serial 1 7 | 8 | # MY_CHECK_STDLIB_LIBCXX([action-if-true], [action-if-false]) 9 | # ------------------------------------------- 10 | # 11 | # Checks whether the current compiler can compile, link and execute 12 | # programs linked with the option -stdlib=libc++. 13 | # In case of success, it executes the `action-if-true', otherwise 14 | # `action-if-false' 15 | AC_DEFUN([MY_CHECK_STDLIB_LIBCXX], [ 16 | AS_VAR_PUSHDEF([CACHEVAR],[my_cv_check_stdlib_libcxx]) 17 | AC_MSG_CHECKING([whether ${_AC_CC} supports the libc++ replacement]) 18 | my_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS 19 | _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS -stdlib=libc++" 20 | AC_RUN_IFELSE([AC_LANG_SOURCE([ 21 | #include 22 | #include 23 | 24 | using namespace std; 25 | 26 | int main(int argc, const char* argv@<:@@:>@){ 27 | cout << "yes" << endl; 28 | return 0; 29 | } 30 | ])], 31 | [AS_VAR_SET(CACHEVAR,[yes]);], dnl The result is written by the cout program 32 | [AS_VAR_SET(CACHEVAR,[no]); AC_MSG_RESULT([no])], 33 | [AS_VAR_SET(CACHEVAR,[maybe]); AC_MSG_RESULT([maybe, cross compiling...])] 34 | ) 35 | _AC_LANG_PREFIX[]FLAGS=${my_check_save_flags} 36 | AS_VAR_IF(CACHEVAR, yes, [m4_default([$1], :)], [m4_default([$2], :)]) 37 | AS_VAR_POPDEF([CACHEVAR]) 38 | ]) 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /build-aux/m4/my_set_cc_flag.m4: -------------------------------------------------------------------------------- 1 | # Set the current compiler option if the given flag is supported 2 | # serial 1 3 | 4 | # MY_SET_CC_FLAG(var_cflags, flag) 5 | # ------------------------------------------- 6 | # 7 | # Test whether is accepted by the current compiler. If so, it appends 8 | # it to the shell variable . 9 | # The macro depends on AX_CHECK_COMPILE_FLAG from the Autoarchive. 10 | AC_DEFUN([MY_SET_CC_FLAG], [ AX_CHECK_COMPILE_FLAG([$2], [AS_VAR_APPEND([$1], " $2")]) ]) -------------------------------------------------------------------------------- /include/teseo/aux/builder.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "teseo/util/abtree.hpp" 25 | 26 | namespace teseo::memstore{ class Key; } // forward declaration 27 | 28 | namespace teseo::aux { 29 | 30 | class CountingTree; // forward declaration 31 | class ItemUndirected; // forward declaration 32 | class PartialResult; // forward declaration 33 | 34 | /** 35 | * Class to create the final degree vectors out of a collection of partial results. 36 | */ 37 | class Builder{ 38 | Builder(const Builder&) = delete; 39 | Builder& operator=(const Builder&) = delete; 40 | 41 | uint64_t m_num_partial_results; // the total number of instances of PartialResults issued 42 | std::mutex m_mutex; // to guarantee thread-safety 43 | std::condition_variable m_condvar; // to signal the builder a new item is available 44 | teseo::util::ABTree m_queue; // the available partial results, as collected from the workers 45 | uint64_t m_num_collected_results; // total number of items fetched from the queue, so far 46 | 47 | public: 48 | // Init the builder 49 | Builder(); 50 | 51 | // Destructor 52 | ~Builder(); 53 | 54 | // Create a new partial result to be computed 55 | PartialResult* issue(const memstore::Key& from, const memstore::Key& to); 56 | 57 | // Collect a partial result previously issued 58 | void collect(PartialResult* partial_result); 59 | 60 | // Fetch the next item from the queue. Return NULL if the queue has been exhausted. 61 | // Remember to explicitly deallocate the item retrieved once used. 62 | PartialResult* next(); 63 | 64 | // Create the degree vector 65 | ItemUndirected* create_dv_undirected(uint64_t num_vertices); 66 | 67 | // Create a counting tree 68 | CountingTree* create_ct_undirected(); 69 | }; 70 | 71 | } // namespace 72 | -------------------------------------------------------------------------------- /include/teseo/aux/cache.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "teseo/context/static_configuration.hpp" // numa_num_nodes 21 | #include "teseo/util/latch.hpp" 22 | 23 | #include 24 | #include 25 | 26 | namespace teseo::gc { class GarbageCollector; } 27 | 28 | namespace teseo::aux { 29 | 30 | class StaticView; // forward declaration 31 | 32 | /** 33 | * Cache for the last created view. Used by the global_context 34 | */ 35 | class Cache { 36 | Cache(const Cache&) = delete; 37 | Cache& operator=(const Cache&) = delete; 38 | constexpr static uint64_t NUM_NODES = context::StaticConfiguration::numa_num_nodes; 39 | static_assert(NUM_NODES >= 1, "We expect to have at least one memory node available"); 40 | 41 | mutable util::Latch m_latch; // to provide thread-safety 42 | uint64_t m_transaction_id; // the read ID associated to the last created view 43 | aux::StaticView* m_views[NUM_NODES]; // the last created view 44 | //gc::GarbageCollector* m_garbage_collector; // to remove the references to leaves 45 | 46 | // Remove the previously cached views 47 | void unset(); // the latch must be held by the invoker 48 | 49 | public: 50 | // Init the cache 51 | Cache(); 52 | 53 | // Destructor 54 | ~Cache(); 55 | 56 | // Retrieve the cached views, if suitable for the given transaction id 57 | bool get(uint64_t transaction_id, uint64_t highest_txn_rw_id, aux::StaticView** output); 58 | 59 | // Update the last saved views 60 | void set(aux::StaticView** views, uint64_t transaction_id); 61 | 62 | // Retrieve a representation of this instance, for debugging purposes 63 | std::string to_string() const; 64 | 65 | // Dump the content of this instance to stdout, for debugging purposes 66 | void dump() const; 67 | }; 68 | 69 | // Dump the content of this instance to the passed output stream, for debugging purposes 70 | std::ostream& operator<<(std::ostream& out, const Cache& cache); 71 | 72 | } // namespace 73 | -------------------------------------------------------------------------------- /include/teseo/aux/cb_serialise_build.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | namespace teseo::aux { 24 | 25 | /** 26 | * The auxiliary snapshot is lazily built when one of the threads in the 27 | * transaction requests it. We want to avoid that multiple threads, belonging 28 | * to the same transaction, do request the creation of the auxiliary snapshot 29 | * concurrently. This class ensures that only one thread can create the snapshot 30 | * while all the others wait for the operation to complete. 31 | */ 32 | class CbSerialiseBuild { 33 | CbSerialiseBuild(const CbSerialiseBuild&) = delete; 34 | CbSerialiseBuild& operator=(const CbSerialiseBuild&) = delete; 35 | 36 | volatile bool m_done; // check 37 | std::mutex m_mutex; // thread safety 38 | std::condition_variable m_condvar; 39 | 40 | public: 41 | // Init the class 42 | CbSerialiseBuild(); 43 | 44 | // Destructor 45 | ~CbSerialiseBuild(); 46 | 47 | // Signal that the build has been completed. Invoked the by thread that performed the build. 48 | void done(); 49 | 50 | // Wait for the auxiliary snapshot to be created. Invoked by all the other threads. 51 | void wait(); 52 | }; 53 | 54 | } // namespace 55 | 56 | -------------------------------------------------------------------------------- /include/teseo/aux/dynamic_view.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "teseo/aux/counting_tree.hpp" 21 | #include "teseo/aux/view.hpp" 22 | #include "teseo/util/latch.hpp" 23 | 24 | namespace teseo::memstore { class Memstore; } // forward declaration 25 | namespace teseo::transaction { class TransactionImpl; } // forward declaration 26 | 27 | namespace teseo::aux { 28 | 29 | /** 30 | * A dynamic mapping between logical IDs and vertex IDs, including their degrees. The view can be 31 | * altered by creating new vertices, removing the existing vertices or modifying the degrees. 32 | * 33 | * This class is thread safe. 34 | */ 35 | class DynamicView : public View { 36 | DynamicView(const DynamicView&) = delete; 37 | DynamicView& operator=(const DynamicView&) = delete; 38 | 39 | CountingTree m_tree; // mapping between vertex ID and logical IDs 40 | mutable util::OptimisticLatch<0> m_latch; // to ensure thread-safety 41 | 42 | // Create a new instance of the view 43 | DynamicView(CountingTree&& tree); 44 | 45 | public: 46 | // Destructor 47 | ~DynamicView(); 48 | 49 | // Retrieve the actual vertex ID associated to the logical ID 50 | // Return NOT_FOUND if the logical_id does not exist 51 | uint64_t vertex_id(uint64_t logical_id) const noexcept; 52 | 53 | // Retrieve the logical ID associated to the vertex ID 54 | // Return NOT_FOUND if vertex_id does not exist 55 | uint64_t logical_id(uint64_t vertex_id) const noexcept; 56 | 57 | // Retrieve the degree associated to the given vertex 58 | // Return NOT_FOUND if the vertex does not exist 59 | uint64_t degree(uint64_t id, bool is_logical) const noexcept; 60 | 61 | // Retrieve the total number of vertices 62 | uint64_t num_vertices() const noexcept; 63 | 64 | // Insert a new vertex in the view. Assume its degree to be 0 65 | void insert_vertex(uint64_t vertex_id); 66 | 67 | // Remove a vertex from the view 68 | void remove_vertex(uint64_t vertex_id); 69 | 70 | // Change the degree of the given vertex 71 | void change_degree(uint64_t vertex_id, int64_t diff); 72 | 73 | // Create a view for the given transaction 74 | static DynamicView* create_undirected(memstore::Memstore* memstore, transaction::TransactionImpl* transaction); 75 | 76 | // Dump the content of the view to stdout, for debugging purposes 77 | void dump() const; 78 | }; 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /include/teseo/aux/item.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "teseo/memstore/index_entry.hpp" 25 | 26 | namespace teseo::aux { 27 | 28 | /** 29 | * The value stored in the degree array for undirected graphs 30 | */ 31 | class ItemUndirected{ 32 | public: 33 | uint64_t m_vertex_id = 0; // the actual vertex id it refers 34 | uint64_t m_degree = 0; // its associated degree, that is the number of edges attached 35 | 36 | // Get a string representation of the item, for debugging purposes 37 | std::string to_string() const; 38 | }; 39 | 40 | // Print to stdout the item, for debugging purposes 41 | std::ostream& operator<<(std::ostream& out, const ItemUndirected& item); 42 | 43 | } // namespace 44 | -------------------------------------------------------------------------------- /include/teseo/aux/partial_result.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #include "teseo/aux/item.hpp" 24 | #include "teseo/memstore/key.hpp" 25 | 26 | namespace teseo::aux { 27 | 28 | class Builder; // forward declaration 29 | 30 | /** 31 | * An ordered chunk of pairs . 32 | * Used by the workers to collect the partial degrees of each vertex, before aggregating 33 | * the final result, the aux vector, in the builder. 34 | * 35 | * This class is not thread-safe. 36 | */ 37 | class PartialResult { 38 | PartialResult(const PartialResult&) = delete; 39 | PartialResult& operator=(const PartialResult&) = delete; 40 | 41 | Builder* const m_builder; // the final builder to process these partial results 42 | const uint64_t m_id; // ordered sequence of IDs, e.g. 0, 1, 2,... used by the builder to reorder the sequence of partial results 43 | const memstore::Key m_from; // the first vertex to insert in the sequence (inclusive), used by the workers to make the partial result 44 | const memstore::Key m_to; // the last vertex to insert in the sequence (exclusive), used by the workers to make the partial result 45 | ItemUndirected* m_array; // the container for the items 46 | int64_t m_last; // the index of the last vertex inserted 47 | uint64_t m_capacity; // the max number of items that can be stored in the container `m_array' 48 | 49 | // Reset the capacity of the container `m_array' 50 | void resize(uint64_t new_capacity); 51 | 52 | public: 53 | // Initialise the class 54 | PartialResult(Builder* builder, uint64_t id, const memstore::Key& from /* incl */, const memstore::Key& to /* excl*/); 55 | 56 | // Destructor 57 | ~PartialResult(); 58 | 59 | // Increment the degree of the given vertex_id 60 | void incr_degree(uint64_t vertex_id, uint64_t increment); 61 | 62 | // Signal to the builder that this partial result is ready to be consumed 63 | void done(); 64 | 65 | // Observer, get the logical ID of this instance 66 | uint64_t id() const noexcept; 67 | 68 | // Observer, get the start key for the range of this instance (inclusive) 69 | const memstore::Key& key_from() const noexcept; 70 | 71 | // Observer, get teh last key for the range of this instance (exclusive) 72 | const memstore::Key& key_to() const noexcept; 73 | 74 | // Check the current capacity of the array 75 | uint64_t capacity() const noexcept; 76 | 77 | // Check the current size of the container 78 | uint64_t size() const noexcept; 79 | 80 | // Is this instance empty? 81 | bool empty() const noexcept; 82 | 83 | // Retrieve the pair at the given position 84 | const ItemUndirected& get(uint64_t index) const; 85 | const ItemUndirected& at(uint64_t index) const; // alias 86 | 87 | // Dump the content of the partial result to stdout, for debugging purposes 88 | void dump() const; 89 | }; 90 | 91 | } // namespace 92 | -------------------------------------------------------------------------------- /include/teseo/aux/view.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "teseo/memstore/index_entry.hpp" 26 | 27 | namespace teseo::gc { class GarbageCollector; } 28 | 29 | namespace teseo::aux { 30 | 31 | /** 32 | * Invocations to the API of AuxiliaryView never throw exceptions. Rather, if 33 | * a vertex does not exist, return the special value NOT_FOUND 34 | */ 35 | constexpr static uint64_t NOT_FOUND = std::numeric_limits::max(); 36 | 37 | /** 38 | * A materialised view to quickly fetch the rank (the logical ID) of a vertex and the 39 | * total number of attached edges. 40 | */ 41 | class View { 42 | View(const View&) = delete; 43 | View& operator=(const View&) = delete; 44 | 45 | const bool m_is_static; // Is the subclass a static or a dynamic view? 46 | std::atomic m_ref_count = 1; // number of references to the class 47 | 48 | protected: 49 | // Destructor, it must be implicitly invoked by #decr_ref_count 50 | virtual ~View(); 51 | 52 | public: 53 | // Initialise the class 54 | View(bool is_static); 55 | 56 | // Retrieve the actual vertex ID associated to the logical ID 57 | // Return NOT_FOUND if the logical_id does not exist 58 | uint64_t vertex_id(uint64_t logical_id) const noexcept; 59 | 60 | // Retrieve the logical ID associated to the vertex ID 61 | // Return NOT_FOUND if vertex_id does not exist 62 | uint64_t logical_id(uint64_t vertex_id) const noexcept; 63 | 64 | // Retrieve the degree associated to the given vertex 65 | // Return NOT_FOUND if the vertex does not exist 66 | uint64_t degree(uint64_t id, bool is_logical) const noexcept; 67 | 68 | // Retrieve the total number of vertices in the view 69 | uint64_t num_vertices() const noexcept; 70 | 71 | // Manage the number of incoming pointers to the class 72 | void incr_ref_count() noexcept; 73 | void decr_ref_count() noexcept; 74 | }; 75 | 76 | } // namespace 77 | 78 | -------------------------------------------------------------------------------- /include/teseo/context/scoped_epoch.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "thread_context.hpp" 21 | 22 | namespace teseo::context { 23 | 24 | /** 25 | * Automatically enter & exit from an epoch in the current thread context 26 | */ 27 | class ScopedEpoch { 28 | const bool m_active; // do not overwrite an epoch already set 29 | 30 | public: 31 | // set the current epoch 32 | ScopedEpoch(); 33 | 34 | // exit from the acquired epoch 35 | ~ScopedEpoch(); 36 | 37 | // update the current epoch 38 | void bump(); 39 | }; 40 | 41 | 42 | /***************************************************************************** 43 | * * 44 | * Implementation details * 45 | * * 46 | *****************************************************************************/ 47 | 48 | inline 49 | ScopedEpoch::ScopedEpoch () : m_active(thread_context()->epoch() == std::numeric_limits::max()) { 50 | bump(); 51 | } 52 | 53 | inline 54 | ScopedEpoch::~ScopedEpoch() { 55 | if(m_active){ thread_context()->epoch_exit(); } 56 | } 57 | 58 | inline 59 | void ScopedEpoch::bump() { 60 | if(m_active){ thread_context()->epoch_enter(); }; 61 | } 62 | 63 | } // namespace 64 | -------------------------------------------------------------------------------- /include/teseo/context/tc_list.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "teseo/util/latch.hpp" 21 | 22 | namespace teseo::context { 23 | 24 | class GlobalContext; // forward decl. 25 | class ThreadContext; // forward decl. 26 | 27 | /** 28 | * The list of all thread contexts registered within a global context 29 | */ 30 | class TcList { 31 | friend class GlobalContext; 32 | TcList(const TcList&) = delete; 33 | TcList& operator=(const TcList&) = delete; 34 | 35 | GlobalContext* const m_global_context; // owner of this list 36 | mutable util::OptimisticLatch<0> m_latch; // provide thread safety 37 | ThreadContext** m_list; // the actual list of elements 38 | volatile uint32_t m_size; // number of elements in the list 39 | uint32_t m_capacity; // number of slots in the list 40 | 41 | // Resize the list to a new capacity 42 | void resize(); 43 | 44 | // The current capacity of the list 45 | uint32_t capacity() const; 46 | 47 | public: 48 | // Constructor 49 | TcList(GlobalContext* global_context); 50 | 51 | // Destructor 52 | ~TcList(); 53 | 54 | // Register a new thread context in the list 55 | void insert(ThreadContext* thread_context); 56 | 57 | // Remove the given thread context from the list 58 | void remove(ThreadContext* thread_context); 59 | 60 | // Retrieve the current list 61 | ThreadContext** list() const; 62 | 63 | // Check whether the list is empty 64 | bool empty() const; 65 | 66 | // Read & validate the internal optimistic latch 67 | uint64_t read_version() const; 68 | void validate_version(uint64_t version) const; 69 | }; 70 | 71 | 72 | /***************************************************************************** 73 | * * 74 | * Implementation details * 75 | * * 76 | *****************************************************************************/ 77 | inline 78 | ThreadContext** TcList::list() const { 79 | return m_list; 80 | } 81 | 82 | inline 83 | uint64_t TcList::read_version() const { 84 | return m_latch.read_version(); 85 | } 86 | 87 | inline 88 | void TcList::validate_version(uint64_t version) const { 89 | m_latch.validate_version(version); 90 | } 91 | 92 | inline 93 | bool TcList::empty() const { 94 | return m_size == 0; 95 | } 96 | 97 | 98 | } // namespace 99 | -------------------------------------------------------------------------------- /include/teseo/gc/garbage_collector.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | #include "teseo/util/latch.hpp" 23 | 24 | namespace teseo::context { class GlobalContext; } // forward declaration 25 | namespace teseo::profiler { class EventThread; } // forward declaration 26 | 27 | namespace teseo::gc { 28 | 29 | class SimpleQueue; // forward declaration 30 | 31 | /** 32 | * An instance of the garbage collector. Each Async/Worker thread owns an instance of 33 | * a garbage collector, to periodically release from memory unused objects. This 34 | * implementation is epoch based. 35 | * 36 | * This class is thread safe. 37 | */ 38 | class GarbageCollector { 39 | context::GlobalContext* m_global_context; // owner 40 | SimpleQueue* m_local; // internal queue, to provide the services of the GC even when a thread context is not available 41 | std::vector m_shared_queues; // queues shared between the GC and a single thread context 42 | std::vector m_private_queues; // queues released by the thread contexts 43 | util::Latch m_latch; // better safe than sorry 44 | profiler::EventThread* m_profiler; // record the GC usage 45 | 46 | // Remove all objects in the given queue 47 | void remove_all(SimpleQueue* queue); 48 | 49 | // Perform a GC pass over the given queue 50 | void perform_gc_pass(uint64_t epoch, SimpleQueue* queue); 51 | 52 | public: 53 | /** 54 | * Create a new instance of the Garbage Collector 55 | */ 56 | GarbageCollector(context::GlobalContext* instance); 57 | 58 | /** 59 | * Destructor 60 | */ 61 | ~GarbageCollector(); 62 | 63 | /** 64 | * Execute a single pass of the garbage collector 65 | */ 66 | void execute(); 67 | 68 | /** 69 | * Create a new queue shared between this garbage collector and a thread context 70 | * @param capacity the initial capacity of the queue (0 = automatic) 71 | */ 72 | SimpleQueue* create_shared_queue(); 73 | 74 | /** 75 | * Return to the GC (unshare) the queues used by a thread context 76 | */ 77 | void unregister(SimpleQueue* local, SimpleQueue* shared); 78 | 79 | /** 80 | * Mark the given object for deletion 81 | */ 82 | void mark(void* pointer, void (*deleter)(void*)); 83 | 84 | /** 85 | * Reset the internal profiler 86 | */ 87 | void set_profiler(profiler::EventThread* profiler); 88 | 89 | /** 90 | * Dump the addresses of the held queues to stdout, for debugging purposes 91 | */ 92 | void dump() const; 93 | }; 94 | 95 | } // namespace 96 | -------------------------------------------------------------------------------- /include/teseo/gc/item.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace teseo::gc { 25 | 26 | /** 27 | * A single entry in the garbage collector 28 | */ 29 | class Item { 30 | uint64_t m_timestamp; // the timestamp when this object has been added to the garbage collector 31 | void* m_pointer; // object to be deleted 32 | void (*m_deleter)(void*); // the function that can remove the pointer 33 | 34 | public: 35 | // Create a dummy entry 36 | Item(); 37 | 38 | // Create a new entry 39 | Item(void* pointer, void (*deleter)(void*)); 40 | 41 | // Process this entry, that is invoke the deleter on the pointer 42 | void process(); 43 | 44 | // Process this entry only iff its timestamp is less than the given epoch 45 | bool process_if(uint64_t epoch); 46 | 47 | // Get the pointer to deallocate, only used for debugging & testing purposes 48 | void* pointer() const; 49 | 50 | // Retrieve a string representation of the item, for debugging purposes 51 | std::string to_string() const; 52 | }; 53 | 54 | // Dump the content of the item to the stdout, for debugging purposes 55 | std::ostream& operator<<(std::ostream& out, const Item& item); 56 | 57 | } // namespace 58 | -------------------------------------------------------------------------------- /include/teseo/gc/simple_queue.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | namespace teseo::gc { 24 | 25 | class Item; // a single entry in the queue 26 | 27 | /** 28 | * The queue shared between a garbage collector and a thread context. 29 | * The idea is that the thread context can only invoke the method #push(), which may fail 30 | * from time to time, returning false. When this happens, the thread context should 31 | * push its item into its local (non shared) queue. 32 | * 33 | * This class is not thread-safe: only one thread context can operate at the time. 34 | */ 35 | class SimpleQueue { 36 | Item* m_array; // the actual queue 37 | uint32_t m_start; // start index (incl) 38 | volatile uint32_t m_end; // last index (excl) 39 | uint32_t m_capacity; // the capacity of the queue 40 | 41 | public: 42 | // Create an empty queue 43 | // @capacity the initiial capacity of the queue ( 0 = auto ) 44 | SimpleQueue(uint32_t capacity = 0); 45 | 46 | // Destructor 47 | ~SimpleQueue(); 48 | 49 | // Is the queue full? 50 | bool full() const; 51 | 52 | // Is the queue empty ? 53 | bool empty() const; 54 | 55 | // Resize the queue, by doubling its capacity 56 | // Precondition: the queue must be full 57 | void resize(); 58 | 59 | // Retrieve the cardinality of the queue 60 | uint64_t size() const; 61 | 62 | // Append a single entry in the queue 63 | bool push(const Item& item); 64 | 65 | // Remove N elements from the queue 66 | void pop(uint64_t num_elements = 1); 67 | 68 | // Retrieve an element at given position 69 | Item& get(int64_t i); 70 | 71 | // Alias for #get 72 | Item& operator[](int64_t i); 73 | 74 | // Dump the content of the array to stdout, for debugging purposes 75 | void dump() const; 76 | }; 77 | 78 | } // namespace 79 | -------------------------------------------------------------------------------- /include/teseo/gc/tc_queue.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "teseo/util/latch.hpp" 21 | 22 | namespace teseo::gc { 23 | 24 | class GarbageCollector; // forward declaration 25 | class SimpleQueue; // forward declaration 26 | 27 | /** 28 | * The queue shared by a thread context a GC, used to collect the objects that need to be 29 | * deleted by the garbage collector. 30 | */ 31 | class TcQueue { 32 | TcQueue(const TcQueue&) = delete; 33 | TcQueue& operator=(const TcQueue&) = delete; 34 | 35 | SimpleQueue* m_local; // private queue 36 | SimpleQueue* m_shared; // queue shared with the garbage collector 37 | GarbageCollector* m_gc; // the garbage collector owner of the queue m_shared 38 | #if !defined(NDEBUG) 39 | const int m_thread_id; // the ID of the thread owning this queue 40 | #endif 41 | 42 | public: 43 | /** 44 | * Create a new thread context queue 45 | */ 46 | TcQueue(GarbageCollector* gc); 47 | 48 | /** 49 | * Destructor 50 | */ 51 | ~TcQueue(); 52 | 53 | /** 54 | * Insert a new element to delete in the queue. 55 | * This method is not thread safe. 56 | */ 57 | void mark(void* pointer, void (*deleter)(void*)); 58 | 59 | /** 60 | * Release the internal queues. No new objects can be marked for GC afterwards. 61 | */ 62 | void release(); 63 | }; 64 | 65 | 66 | } // namespace 67 | 68 | -------------------------------------------------------------------------------- /include/teseo/memstore/cursor_state.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "teseo/memstore/context.hpp" 25 | #include "teseo/memstore/direct_pointer.hpp" 26 | #include "teseo/memstore/key.hpp" 27 | 28 | namespace teseo::memstore { 29 | 30 | /** 31 | * This is the saved state of an iterator. It can be eventually reloaded to resume the 32 | * scan from its last saved position. 33 | * 34 | * This instance can only be used with regular (non optimistic) readers on sparse files. When a reader 35 | * saves its state, it doesn't release the held latch to the segment. The latch must be eventually 36 | * released by invoking the method #close() on this class. 37 | */ 38 | class CursorState { 39 | Key m_key; // The next key to read in the cursor 40 | DirectPointer m_position; // The last position of the cursor 41 | 42 | public: 43 | /** 44 | * Create a new (empty) instance 45 | */ 46 | CursorState(); 47 | 48 | /** 49 | * Destroy the instance 50 | */ 51 | ~CursorState(); 52 | 53 | /** 54 | * Invalidate the state, but do not release the held latch 55 | */ 56 | void invalidate() noexcept; 57 | 58 | /** 59 | * Invalidate the state and the release the held latch 60 | */ 61 | void close() noexcept; 62 | 63 | /** 64 | * Retrieve the key associated to this cursor 65 | */ 66 | Key& key(); 67 | const Key& key() const; 68 | 69 | 70 | /** 71 | * Check if the current instance is still valid, that is, it has not been invalidated or closed. 72 | */ 73 | bool is_valid() const; 74 | 75 | /** 76 | * Retrieve the direct pointer associated to this cursor 77 | */ 78 | DirectPointer& position(); 79 | const DirectPointer& position() const; 80 | 81 | /** 82 | * Retrieve a string representation of the state, for debugging purposes 83 | */ 84 | std::string to_string() const; 85 | 86 | /** 87 | * Dump the content of the cursor to the output stream, for debugging purposes 88 | */ 89 | void dump() const; 90 | }; 91 | 92 | /** 93 | * Print a string representation of the cursor. 94 | */ 95 | std::ostream& operator<<(std::ostream& out, const CursorState& bookmark); 96 | 97 | 98 | /***************************************************************************** 99 | * * 100 | * Implementation details * 101 | * * 102 | *****************************************************************************/ 103 | inline 104 | Key& CursorState::key() { 105 | return m_key; 106 | } 107 | 108 | inline 109 | const Key& CursorState::key() const { 110 | return m_key; 111 | } 112 | 113 | inline 114 | DirectPointer& CursorState::position() { 115 | return m_position; 116 | } 117 | 118 | inline 119 | const DirectPointer& CursorState::position() const { 120 | return m_position; 121 | } 122 | 123 | inline 124 | bool CursorState::is_valid() const { 125 | return m_key != KEY_MIN; 126 | } 127 | 128 | } // namespace 129 | -------------------------------------------------------------------------------- /include/teseo/memstore/error.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | #include "key.hpp" 23 | 24 | namespace teseo::memstore { 25 | 26 | 27 | /** 28 | * The collection of exceptions that can be thrown during an update in the memstore 29 | */ 30 | struct Error { 31 | Key m_key; // pair 32 | 33 | enum Type { 34 | VertexLocked, // -> Transaction conflict 35 | VertexAlreadyExists, 36 | VertexDoesNotExist, 37 | VertexPhantomWrite, // Trying to update an edge while one of its endpoints is concurrently being removed 38 | VertexInvalidLogicalID, // Invalid value for a logical vertex. Its value is not in [0, num_vertices) 39 | EdgeLocked, // -> Transaction conflict 40 | EdgeAlreadyExists, 41 | EdgeDoesNotExist, 42 | EdgeSelf, // source and destination are the same, a -> a 43 | TooManyReaders, // there are too many readers accessing the same segment, causing a counter overflow 44 | }; 45 | 46 | Type m_type; 47 | 48 | Error(Key key, Type type) : m_key(key), m_type(type) {} 49 | }; 50 | 51 | 52 | /** 53 | * Internal exception thrown by SparseFile#insert_edge() when it's not sure whether the source vertex exists 54 | * in the sparse array. The caller should verify the existence of the vertex and then invoke the method 55 | * again #insert_edge() disabling the flag for this check. 56 | */ 57 | struct NotSureIfItHasSourceVertex{}; 58 | 59 | } 60 | -------------------------------------------------------------------------------- /include/teseo/memstore/latch_state.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace teseo::memstore { 25 | 26 | /** 27 | * This class provides information about the current state of a segment's latch. It is only used 28 | * for debugging and testing purposing. 29 | */ 30 | class LatchState { 31 | public: 32 | const bool m_invalid = false; // true if the segment is part of a leaf that has been deleted, due to a resize or a merge. 33 | const bool m_xlock = false; // true if an xlock is currently acquired in the segment. That is some thread is changing the segment meta-information, e.g. managing the waiting queue. 34 | const bool m_writer = false; // true if a writer is currently operating in the segment. 35 | const bool m_rebalancer = false; // true if a rebalancer is currently operating in the segment. 36 | const bool m_wait = false; // true if there is at least one thread waiting in the queue 37 | const uint64_t m_readers = 0; // the current number of readers operating in the segment 38 | const uint64_t m_version = 0; // the current version of the latch, incremented after each write in the segment 39 | 40 | /** 41 | * Init the class with the content of the latch 42 | */ 43 | LatchState(uint64_t latch); 44 | 45 | /** 46 | * Retrieve a string representation of this instance 47 | */ 48 | std::string to_string() const; 49 | }; 50 | 51 | // Dump the content of the instance to the given output stream 52 | std::ostream& operator<<(std::ostream& out, const LatchState& ls); 53 | 54 | } 55 | -------------------------------------------------------------------------------- /include/teseo/memstore/wake_list.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | namespace teseo::memstore { 23 | 24 | /** 25 | * This is a list of threads that needs to be awaken after the latch associated to 26 | * a segment has been released 27 | */ 28 | class WakeList { 29 | WakeList(const WakeList&) = delete; 30 | WakeList& operator=(const WakeList&) = delete; 31 | 32 | // This is an optimisation 33 | // The encoding is: 34 | // m_list == nullptr, then the list is empty 35 | // m_list % 2 == 1 => m_list contains a ptr to a single future to wake up 36 | // m_list % 2 == 0 => m_list[0] contains the length of the list, and m_list[1], m_list[2], ... are the futures to release 37 | void* m_list = nullptr; 38 | 39 | public: 40 | // Create an empty instance 41 | WakeList() noexcept; 42 | 43 | // Move the content of the list 44 | WakeList(WakeList&& copy) noexcept; 45 | WakeList& operator=(WakeList&& copy) noexcept; 46 | 47 | // Destructor 48 | ~WakeList(); 49 | 50 | // Empty the content of the list 51 | void reset() noexcept; 52 | 53 | // Set the content of the list to the first N elements of the priority queue. The copied elements are removed from 54 | // the priority queue. 55 | // @param queue a reference to the segment's internal priority queue 56 | // @param n the number of elements to copy 57 | void set(void* queue, uint64_t n = 1); 58 | 59 | // Wake all threads in the list 60 | void wake() noexcept; 61 | }; 62 | 63 | } // namespace 64 | -------------------------------------------------------------------------------- /include/teseo/profiler/direct_access.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #include "teseo/context/global_context.hpp" 24 | 25 | //#define HAVE_PROFILER_DIRECT_ACCESS 26 | 27 | namespace teseo::profiler { 28 | 29 | #if defined(HAVE_PROFILER_DIRECT_ACCESS) 30 | 31 | class DirectAccessCounters { 32 | DirectAccessCounters(const DirectAccessCounters&) = delete; 33 | DirectAccessCounters& operator=(const DirectAccessCounters&) = delete; 34 | 35 | public: 36 | std::atomic m_memstore_invocations = 0; // total amount of invocations of the method Memstore#scan 37 | std::atomic m_memstore_cs_present = 0; // total number of invocations to the method #can having a cursor state 38 | std::atomic m_memstore_cs_key_match = 0; // cursor state match (expected key == requested key) 39 | std::atomic m_memstore_cs_fkeys_match = 0; // cursor state partial match, same fence key 40 | std::atomic m_memstore_cs_dptr_match = 0; // cursor state partial match, direct pointer match 41 | std::atomic m_memstore_cs_no_filepos = 0; // cursor state partial match, no filepos available 42 | std::atomic m_memstore_cs_no_match = 0; // cursor state present, but it doesn't match the key (release the latch) 43 | std::atomic m_memstore_vt_lookups = 0; // total number of look ups to the vertex table, when not using the code path of the cursor state 44 | std::atomic m_memstore_vt_fkeys_match = 0; // the fence keys match 45 | std::atomic m_memstore_vt_invalid_filepos = 0; // the segment's version does not match 46 | std::atomic m_context_invocations = 0; // total amount of calls to the method Context#reader_direct_access 47 | std::atomic m_context_dptr_set = 0; // total number of invocations with a direct pointer set 48 | std::atomic m_context_invalid_filepos = 0; // either the filepos or the segment ID do not match 49 | std::atomic m_context_dptr_success = 0; // # successes with a direct pointer set 50 | std::atomic m_context_dptr_failure = 0; // # failures (aborts) with a direct pointer set 51 | std::atomic m_context_conventional = 0; // total number of accesses falling back to ART 52 | std::atomic m_context_retry = 0; // number of retries when using a conventional access 53 | 54 | public: 55 | // Constructor 56 | DirectAccessCounters(); 57 | 58 | // Destructor 59 | ~DirectAccessCounters(); 60 | 61 | // Reset all counters 62 | void reset(); 63 | 64 | // Dump to stdout the counters 65 | void dump(); 66 | }; 67 | 68 | #define PROFILE_DIRECT_ACCESS(name) ::teseo::context::global_context()->profiler_direct_access()->m_##name ++ 69 | 70 | #else 71 | 72 | class DirectAccessCounters { 73 | public: 74 | void reset() { } 75 | void dump() { } 76 | }; 77 | #define PROFILE_DIRECT_ACCESS(name) 78 | 79 | #endif 80 | 81 | } // namespace 82 | -------------------------------------------------------------------------------- /include/teseo/profiler/event_global.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "teseo/util/latch.hpp" 26 | 27 | namespace teseo::profiler { 28 | 29 | class EventThread; // forward decl. 30 | 31 | /** 32 | * List of all events recorded in the terminated ThreadContexts 33 | */ 34 | class EventGlobal { 35 | std::vector m_event_threads; // list of terminated event threads 36 | const std::chrono::time_point m_time_ctor; // when the instance was created 37 | util::Latch m_latch; // make the method #acquire thread safe 38 | 39 | public: 40 | /** 41 | * Create a new instance 42 | */ 43 | EventGlobal(); 44 | 45 | /** 46 | * Destructor 47 | */ 48 | ~EventGlobal(); 49 | 50 | /** 51 | * Load the given event thread into the global list 52 | */ 53 | void acquire(EventThread* ev_thread); 54 | 55 | /** 56 | * Dump the recorded events in json format to the given output stream 57 | */ 58 | void to_json(std::ostream& out) const; 59 | 60 | }; 61 | 62 | } 63 | -------------------------------------------------------------------------------- /include/teseo/profiler/event_list.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #include "teseo/profiler/event_name.hpp" 24 | #include "teseo/third-party/magic_enum.hpp" 25 | 26 | namespace teseo::profiler { 27 | 28 | struct EventData { 29 | EventData(const EventData&) = delete; 30 | EventData& operator=(const EventData& ) = delete; 31 | EventData() { } 32 | 33 | std::chrono::microseconds m_total_time; 34 | uint64_t m_num_scoped_timers = 0; 35 | uint64_t m_num_invocations = 0; 36 | }; 37 | 38 | using EventList = std::array()>; 39 | 40 | } // namaspace 41 | -------------------------------------------------------------------------------- /include/teseo/profiler/event_thread.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #include "teseo/profiler/event_list.hpp" 24 | 25 | namespace teseo::profiler { 26 | 27 | class EventThread { 28 | EventList m_event_list; 29 | uint64_t m_thread_id; 30 | std::string m_thread_name; 31 | std::chrono::time_point m_time_ctor; // when the instance was created 32 | std::chrono::time_point m_time_dtor; // when this instance was removed from the thread context 33 | 34 | public: 35 | /** 36 | * Init the instance 37 | */ 38 | EventThread(); 39 | 40 | /** 41 | * Mark as completed the usage of this instance 42 | */ 43 | void close(); 44 | 45 | /** 46 | * Check whether there have been any event recording 47 | */ 48 | bool has_events() const; 49 | 50 | /** 51 | * Retrieve the data associated to the given event 52 | */ 53 | EventData* get_event(EventName event){ 54 | return &(m_event_list[(int) event]); 55 | } 56 | 57 | /** 58 | * Dump the recorded events in json format to the given output stream 59 | */ 60 | void to_json(std::ostream& out) const; 61 | }; 62 | 63 | } // namespace 64 | -------------------------------------------------------------------------------- /include/teseo/profiler/rebal_global_list.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | #include "teseo/profiler/rebal_list.hpp" 24 | #include "teseo/util/latch.hpp" 25 | 26 | namespace teseo::profiler { 27 | 28 | /** 29 | * The sequence of recordings, but maintain a sequence for each thread type 30 | */ 31 | class GlobalRebalanceList { 32 | std::array m_lists; // recordings for each thread type 33 | std::array m_num_threads; // number of registered threads in each list 34 | util::Latch m_latch; // make the method #insert thread safe 35 | 36 | 37 | public: 38 | /** 39 | * Constructor 40 | */ 41 | GlobalRebalanceList(); 42 | 43 | /** 44 | * Save the given recordings 45 | */ 46 | void insert(const RebalanceList* list); 47 | 48 | /** 49 | * Dump the recording into a json 50 | */ 51 | void to_json(std::ostream& out); 52 | }; 53 | 54 | } // namespace 55 | -------------------------------------------------------------------------------- /include/teseo/profiler/rebal_list.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "rebal_stats.hpp" 21 | 22 | namespace teseo::profiler { 23 | 24 | /** 25 | * Thread type 26 | */ 27 | enum class ThreadType : int { WORKER, MERGER, ASYNC, AUTO /* determine it by the thread name */ }; 28 | 29 | 30 | /** 31 | * A sequence of recordings 32 | */ 33 | class RebalanceList { 34 | std::vector m_list; // the recordings saved so far 35 | ThreadType m_thread_type; // the type of thread associated to this statistics 36 | 37 | public: 38 | /** 39 | * Constructor 40 | */ 41 | RebalanceList(ThreadType type = ThreadType::AUTO); 42 | 43 | /** 44 | * The type of thread associated to this statistics 45 | */ 46 | ThreadType thread_type() const; 47 | 48 | /** 49 | * Save the given recordings 50 | */ 51 | void insert(const RebalanceRecordedStats& stats); 52 | 53 | /** 54 | * Merge the rebalancing list 55 | */ 56 | void insert(const RebalanceList* list); 57 | 58 | /** 59 | * Compute the statistics for the saved recordings 60 | */ 61 | RebalanceCompleteStatistics statistics(); 62 | }; 63 | 64 | 65 | } // namespace 66 | -------------------------------------------------------------------------------- /include/teseo/profiler/rebal_profiler.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "rebal_stats.hpp" 21 | #include "rebal_timer.hpp" 22 | 23 | // Forward declaration 24 | namespace teseo::rebalance { class Plan; } 25 | 26 | namespace teseo::profiler { 27 | 28 | /** 29 | * Single statistics attached to a single rebalancing task 30 | */ 31 | #if defined(HAVE_PROFILER) 32 | class RebalanceProfiler { 33 | std::chrono::time_point m_time_created; // when this instance was created 34 | RebalanceRecordedStats m_fields; // remaining stats 35 | 36 | public: 37 | RebalanceProfiler(const rebalance::Plan& plan); 38 | 39 | // Destructor 40 | ~RebalanceProfiler(); 41 | 42 | void set_window_length(uint64_t num_segments); 43 | 44 | RebalanceTimer profile_load_time(){ 45 | return RebalanceTimer(&m_fields.m_load_time); 46 | } 47 | 48 | RebalanceTimer profile_write_time(){ 49 | return RebalanceTimer(&m_fields.m_write_time); 50 | } 51 | 52 | RebalanceTimer profile_prune_time(bool start_immediately){ 53 | return RebalanceTimer(&m_fields.m_prune_time); 54 | } 55 | 56 | void incr_count_in_num_qwords(int64_t v = 1) { m_fields.m_in_num_qwords += v; } 57 | void incr_count_in_num_elts(int64_t v = 1){ m_fields.m_in_num_elts += v; } 58 | void incr_count_in_num_vertices(int64_t v = 1){ m_fields.m_in_num_vertices += v; } 59 | void incr_count_in_num_edges(int64_t v = 1){ m_fields.m_in_num_edges += v; } 60 | void incr_count_out_num_qwords(int64_t v = 1) { m_fields.m_out_num_qwords += v; } 61 | void incr_count_out_num_elts(int64_t v = 1){ m_fields.m_out_num_elts += v; } 62 | void incr_count_out_num_vertices(int64_t v = 1){ m_fields.m_out_num_vertices += v; } 63 | void incr_count_out_num_edges(int64_t v =1){ m_fields.m_out_num_edges += v; } 64 | }; 65 | 66 | #else 67 | 68 | // Dummy class 69 | class RebalanceProfiler { 70 | public: 71 | RebalanceProfiler(const rebalance::Plan& plan){ } ; 72 | void set_window_length(uint64_t num_segments){ }; 73 | RebalanceTimer profile_load_time(){ return RebalanceTimer(); } 74 | RebalanceTimer profile_write_time(){ return RebalanceTimer(); } 75 | RebalanceTimer profile_prune_time(bool start_immediately){ return RebalanceTimer(); } 76 | void incr_count_in_num_qwords(int64_t v = 1) { } 77 | void incr_count_in_num_elts(int64_t v = 1){ } 78 | void incr_count_in_num_vertices(int64_t v = 1){ } 79 | void incr_count_in_num_edges(int64_t v = 1){ } 80 | void incr_count_out_num_qwords(int64_t v = 1) { } 81 | void incr_count_out_num_elts(int64_t v = 1){ } 82 | void incr_count_out_num_vertices(int64_t v = 1){ } 83 | void incr_count_out_num_edges(int64_t v =1){ } 84 | }; 85 | 86 | #endif 87 | 88 | } // namespace 89 | -------------------------------------------------------------------------------- /include/teseo/profiler/rebal_time_unit.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | namespace teseo::profiler { 23 | 24 | /** 25 | * The internal granularity of the timer 26 | */ 27 | using RebalanceTimeUnit = std::chrono::nanoseconds; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /include/teseo/profiler/rebal_timer.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | #include "teseo/profiler/rebal_time_unit.hpp" 23 | #include "teseo/util/timer.hpp" 24 | 25 | namespace teseo::profiler { 26 | 27 | #if defined(HAVE_PROFILER) 28 | /** 29 | * Simple timer to account the duration of a task inside a rebalance 30 | */ 31 | class RebalanceTimer { 32 | RebalanceTimer(const RebalanceTimer&) = delete; 33 | RebalanceTimer& operator=(const RebalanceTimer&) = delete; 34 | 35 | 36 | RebalanceTimeUnit* m_counter; // pointer to the event data 37 | util::Timer m_timer; // internal timer 38 | 39 | public: 40 | // Create a timer for the given counter 41 | RebalanceTimer(RebalanceTimeUnit* counter, bool start_immediately = true) : m_counter(counter) { 42 | if(start_immediately) start(); 43 | } 44 | 45 | // Destructor 46 | ~RebalanceTimer(){ 47 | stop(); 48 | *m_counter += m_timer.duration(); 49 | } 50 | 51 | // Restart the timer 52 | void start(){ m_timer.resume(); } 53 | 54 | // Stop the timer 55 | void stop() { m_timer.stop(); } 56 | }; 57 | 58 | #else 59 | // Dummy class 60 | class RebalanceTimer { 61 | public: 62 | RebalanceTimer(){ }; 63 | void start(){ } 64 | void stop(){ } 65 | }; 66 | #endif 67 | 68 | } 69 | -------------------------------------------------------------------------------- /include/teseo/profiler/save_to_disk.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | 21 | namespace teseo::profiler { 22 | 23 | class EventGlobal; // forward declaration 24 | class GlobalRebalanceList; // forward declaration 25 | 26 | /** 27 | * Save the recorded events to a .json file in the disk 28 | */ 29 | void save_to_disk(EventGlobal* global_events, GlobalRebalanceList* rebalance_events); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /include/teseo/profiler/scoped_timer.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "teseo/profiler/event_name.hpp" 21 | #include "teseo/util/timer.hpp" 22 | namespace teseo::profiler { 23 | 24 | struct EventData; // forward decl. 25 | class EventThread; // forward decl. 26 | 27 | 28 | #if defined(HAVE_PROFILER) 29 | /** 30 | * A timer to account the time passed in some event 31 | */ 32 | class ScopedTimer { 33 | EventData* m_event; // pointer to the event data 34 | util::Timer m_timer; // internal timer 35 | 36 | public: 37 | // Create a timer for the given event 38 | ScopedTimer(EventName event, bool start_immediately = true); 39 | 40 | // As above, explicitly specify the event thread 41 | ScopedTimer(EventName event, EventThread* evthread, bool start_immediately = true); 42 | 43 | // Destructor 44 | ~ScopedTimer(); 45 | 46 | // Restart the timer 47 | void start(); 48 | 49 | // Stop the timer 50 | void stop(); 51 | }; 52 | 53 | 54 | #else 55 | // Dummy class 56 | class ScopedTimer { 57 | public: 58 | ScopedTimer(EventName event, bool start_immediately = true){ }; 59 | ScopedTimer(EventName event, EventThread* thread, bool start_immediately = true){ }; 60 | void start(){ } 61 | void stop(){ } 62 | }; 63 | #endif 64 | 65 | } 66 | 67 | -------------------------------------------------------------------------------- /include/teseo/rebalance/merge_operator.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "teseo/memstore/context.hpp" 21 | 22 | namespace teseo::rebalance { 23 | 24 | class ScratchPad; // forward decl. 25 | 26 | /** 27 | * This class traverses the leaves in a sparse array, pruning obsolete records 28 | * and merging together consecutive leaves, where possible. 29 | */ 30 | class MergeOperator { 31 | memstore::Context m_context; // ptr to the path memstore -> leaf -> segment 32 | ScratchPad* m_scratchpad; // working area, used to merge leaves together 33 | 34 | /** 35 | * Visit the current leaf, prune all the old records and return and estimate of the 36 | * number of slots in use 37 | */ 38 | uint64_t visit_and_prune(); 39 | 40 | /** 41 | * Merge the content of the leaves `previous' and `current' 42 | */ 43 | std::pair merge(memstore::Leaf* previous, memstore::Leaf* current, uint64_t cardinality, uint64_t used_space); 44 | 45 | public: 46 | /** 47 | * Create a new instance of the operator 48 | */ 49 | MergeOperator(const memstore::Context& context); 50 | 51 | /** 52 | * Destructor 53 | */ 54 | ~MergeOperator(); 55 | 56 | /** 57 | * Execute the operator! 58 | */ 59 | void execute(); 60 | }; 61 | 62 | } 63 | -------------------------------------------------------------------------------- /include/teseo/rebalance/merger_service.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | struct event; // libevent forward decl. 24 | struct event_base; // libevent forward decl. 25 | namespace teseo::memstore { class Memstore; } // forward declaration 26 | 27 | namespace teseo::rebalance { 28 | 29 | /** 30 | * This is a service attached to a single sparse array. It periodically runs 31 | * on a background thread. It prunes obsolete version/undo records from the 32 | * sparse array and, where possible, merges two smaller chunks into a single 33 | * large chunk. 34 | */ 35 | class MergerService { 36 | struct event_base* m_queue; // libevent's queue 37 | std::thread m_background_thread; // handle to the background thread 38 | bool m_eventloop_exec; // true when the service thread is running the event loop 39 | memstore::Memstore* const m_memstore; // the attached sparse array instance 40 | 41 | // Method executed by the background thread, it runs the event loop 42 | void main_thread(); 43 | 44 | // Notify the thread who started the service that the event loop is running 45 | static void callback_start(int fd, short flags, void* /* MergerService instance */ event_argument); 46 | 47 | // Trampoline to invoke the actual Merger routine 48 | static void callback_execute(int fd, short flags, void* /* MergerCallbackData */ event_argument); 49 | 50 | public: 51 | /** 52 | * Create a new instance of the service 53 | * @param owner pointer to the related Memstore instance 54 | */ 55 | MergerService(memstore::Memstore* owner); 56 | 57 | /** 58 | * Destructor 59 | */ 60 | ~MergerService(); 61 | 62 | /** 63 | * Start the service 64 | */ 65 | void start(); 66 | 67 | /** 68 | * Stop the service 69 | */ 70 | void stop(); 71 | 72 | /** 73 | * Invoke the service synchronously, for debugging purposes 74 | */ 75 | void execute_now(); 76 | }; 77 | 78 | } // namespace 79 | 80 | -------------------------------------------------------------------------------- /include/teseo/rebalance/rebalance.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | namespace teseo::memstore { 21 | class Context; 22 | class Key; 23 | class Memstore; 24 | } 25 | 26 | namespace teseo::rebalance { 27 | 28 | /** 29 | * Handle a request to rebalance the given segment 30 | */ 31 | void handle_rebalance(memstore::Memstore* memstore, memstore::Key& key); 32 | 33 | 34 | } // namespace 35 | -------------------------------------------------------------------------------- /include/teseo/rebalance/rebalanced_leaf.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace teseo::memstore { class Leaf; } // forward declaration 25 | 26 | namespace teseo::rebalance { 27 | 28 | /** 29 | * The state of a single leaf rebalanced. Used internally by the SpreadOperator to keep track 30 | * of the locks used in a leaf 31 | */ 32 | class RebalancedLeaf { 33 | memstore::Leaf* const m_leaf; // pointer to the underlying leaf 34 | const uint16_t m_window_start; // the first segment rebalanced in the leaf 35 | const uint16_t m_window_length; // total number of segments rebalanced 36 | uint32_t m_flags = 0; // whether the leaf already exists, has been just created or it is due to deletion 37 | 38 | const uint32_t FLAG_EXISTENT = 0x1; // the leaf already exists 39 | const uint32_t FLAG_CREATED = 0x2; // this leaf has just been created by the spread operator 40 | const uint32_t FLAG_REMOVED = 0x4; // this leaf must be removed 41 | 42 | // Set the given flag 43 | void set_flag(uint32_t flag, int value) noexcept; 44 | 45 | // Get the value associated to the given flag 46 | int get_flag(uint32_t flag) const noexcept; 47 | 48 | public: 49 | // Create the state for the given leaf 50 | RebalancedLeaf(memstore::Leaf* leaf) noexcept; 51 | 52 | // Create the state for the given leaf. Explicitly set the window being rebalanced. 53 | RebalancedLeaf(memstore::Leaf* leaf, uint64_t /* incl */ window_start, uint64_t /* excl */ window_end) noexcept; 54 | 55 | // Obtain a pointer to the leaf being rebalanced 56 | memstore::Leaf* leaf() const noexcept; 57 | 58 | // Get the start of the window being rebalanced (inclusive) 59 | uint64_t window_start() const noexcept; 60 | 61 | // Get the end of the window being rebalanced (exclusive) 62 | uint64_t window_end() const noexcept; 63 | 64 | // Get the number of the segments in the window being rebalanced 65 | uint64_t window_length() const noexcept; 66 | 67 | // Mark the window as already existing 68 | void set_existent() noexcept; 69 | 70 | // Mark the window as just been created by a spread operation 71 | void set_created() noexcept; 72 | 73 | // Mark the window for deletion 74 | void set_removed() noexcept; 75 | 76 | // Check whether this leaf already exists 77 | bool is_existent() const noexcept; 78 | 79 | // Check whether this leaf was marked as just been created 80 | bool is_created() const noexcept; 81 | 82 | // Check whether this leaf was marked for deletion 83 | bool is_removed() const noexcept; 84 | 85 | // Get a string representation of this instance, for debugging purposes 86 | std::string to_string() const; 87 | 88 | // Dump the content of this instance to stdout, for debugging purposes 89 | void dump() const; 90 | }; 91 | 92 | // Dump the content of the state of the leaf to the given output stream 93 | std::ostream& operator<<(std::ostream& out, const RebalancedLeaf& leaf); 94 | 95 | } // namespace 96 | -------------------------------------------------------------------------------- /include/teseo/rebalance/weighted_edge.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | // Forward declarations 24 | namespace teseo::memstore { 25 | class Version; 26 | class Vertex; 27 | } // namespace 28 | 29 | namespace teseo::rebalance { 30 | 31 | /** 32 | * The representation of an edge in a Rebalancer scratchpad 33 | */ 34 | class WeightedEdge { 35 | public: 36 | uint64_t m_destination; 37 | double m_weight; 38 | 39 | // Get a string representation of this edge, for debugging purposes 40 | std::string to_string(const memstore::Vertex* source, const memstore::Version* version) const; 41 | }; 42 | 43 | } // namespace 44 | -------------------------------------------------------------------------------- /include/teseo/runtime/queue.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "task.hpp" 21 | 22 | #include 23 | #include 24 | 25 | #include "teseo/context/static_configuration.hpp" 26 | #include "teseo/runtime/task.hpp" 27 | #include "teseo/util/circular_array.hpp" 28 | 29 | // forward declarations 30 | namespace teseo::context { class GlobalContext; } 31 | namespace teseo::gc { class GarbageCollector; } 32 | namespace teseo::runtime { class Runtime; } 33 | namespace teseo::runtime { class Worker; } 34 | 35 | namespace teseo::runtime { 36 | 37 | class Queue { 38 | const int m_num_workers; // total number of workers 39 | struct WState { 40 | Worker* m_worker; 41 | std::mutex m_mutex; 42 | std::condition_variable m_condvar; 43 | util::CircularArray m_queue; 44 | }; 45 | WState* m_workers; // The pointer & the queue associated to each worker 46 | runtime::Runtime* const m_runtime; // Pointer to the owner of this instance 47 | 48 | // Start all the workers 49 | void start_workers(); 50 | 51 | // Send a request to terminate all workers, wait for their threads to terminate 52 | void stop_workers(); 53 | 54 | public: 55 | // Constructor, start the workers 56 | Queue(runtime::Runtime* runtime); 57 | 58 | // Destructor, terminate the workers 59 | ~Queue(); 60 | 61 | // Submit the task to a specific worker 62 | void submit(Task task, int worker_id); 63 | 64 | // Submit the given task to all workers 65 | void submit_all(Task task); 66 | 67 | // Fetch the runtime instance associated to this set of queues 68 | runtime::Runtime* runtime(); 69 | 70 | // Retrieve one of the workers randomly 71 | int random_worker_id(); 72 | 73 | // Retrieve a random worker 74 | Worker* random_worker(); 75 | 76 | // Retrieve the worker associated to the given ID 77 | Worker* get_worker(int worker_id); 78 | 79 | // Total number of workers 80 | int num_workers() const; 81 | 82 | // Fetch the next task to process. This method is invoked by workers. 83 | Task fetch(int worker_id); 84 | }; 85 | 86 | /***************************************************************************** 87 | * * 88 | * Implementation details * 89 | * * 90 | *****************************************************************************/ 91 | inline 92 | int Queue::num_workers() const { 93 | return m_num_workers; 94 | } 95 | 96 | } // namespace 97 | -------------------------------------------------------------------------------- /include/teseo/runtime/timer_service.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "teseo/gc/tc_queue.hpp" 25 | #include "teseo/runtime/task.hpp" 26 | 27 | struct event; // libevent forward decl. 28 | struct event_base; // libevent forward decl. 29 | 30 | namespace teseo::context { class GlobalContext; } // forward decl. 31 | namespace teseo::context { class ThreadContext; } // forward decl. 32 | namespace teseo::memstore { class Memstore; } // forward decl. 33 | namespace teseo::runtime { class Runtime; } // forward decl. 34 | 35 | namespace teseo::runtime { 36 | 37 | class TimerService { 38 | struct event_base* m_queue; // libevent's queue 39 | runtime::Runtime* const m_runtime; // owner of this instance 40 | std::thread m_background_thread; // handle to the background thread 41 | bool m_eventloop_exec; // true when the service thread is running the event loop 42 | gc::TcQueue* m_gc_queue; // internal GC queue 43 | 44 | // Event loop 45 | void main_thread(); 46 | 47 | // Notify the thread who started the service that the event loop is running 48 | static void callback_start(int fd, short flags, void* /* TimerService instance */ event_argument); 49 | 50 | // Callback to reset the current cached transaction list inside a thread context 51 | static void callback_active_transactions(int fd, short flags, void* /* ActiveTransactionsEvent */ event_argument); 52 | struct EventActiveTransactions { struct event* m_event; gc::TcQueue* m_gc; context::ThreadContext* m_thread_context; }; 53 | 54 | // Forward the event to the runtime 55 | static void callback_runtime(int fd, short flags, void* /* RuntimeEvent */ event_argument); 56 | struct EventRuntime { struct event* m_event; runtime::Runtime* m_runtime; Task m_task; int m_worker_id; }; 57 | 58 | // Remove the pending events still in the queue 59 | void remove_pending_events(); 60 | 61 | public: 62 | // Constructor. It implicitly starts the service. 63 | TimerService(runtime::Runtime* runtime); 64 | 65 | // Destructor. It implicitly stops the running service. 66 | ~TimerService(); 67 | 68 | // Start the service / background thread 69 | void start(); 70 | 71 | // Stop the service / background thread 72 | void stop(); 73 | 74 | // Request to asynchronously delete the cache of active transactions in the current thread context 75 | void refresh_active_transactions(); 76 | 77 | // Request to schedule a rebalance for the given segment 78 | void schedule_task(Task task, int worker_id, std::chrono::milliseconds when); 79 | }; 80 | 81 | } // namespace 82 | -------------------------------------------------------------------------------- /include/teseo/runtime/worker.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | 23 | namespace teseo::gc { class GarbageCollector; } 24 | namespace teseo::transaction { class MemoryPoolList; } 25 | 26 | namespace teseo::runtime { 27 | 28 | class Queue; // forward declaration 29 | 30 | /** 31 | * A background thread performing various maintenance tasks asynchronously, upon request 32 | * of the Master and the rest of the system. 33 | */ 34 | class Worker { 35 | Worker(Worker&) = delete; 36 | Worker& operator= (const Worker&) = delete; 37 | Queue* m_worker_pool; // the master service 38 | const int m_id; // the worker id 39 | transaction::MemoryPoolList* m_transaction_pool; // cache of memory pools used by thread contexts to create new transactions 40 | gc::GarbageCollector* m_gc; // every worker has its own garbage collector! 41 | std::thread m_thread; // handle to the background thread 42 | 43 | // Helper, set the name of this thread, for debugging purposes 44 | static void set_thread_name(int worker_id); 45 | 46 | // Event loop for the background thread 47 | void main_thread(); 48 | 49 | public: 50 | // Create & start a worker 51 | Worker(Queue* pool, int worker_id); 52 | 53 | // Destructor, wait for the background thread to terminate 54 | ~Worker(); 55 | 56 | // Handle to the garbage collector 57 | gc::GarbageCollector* gc(); 58 | 59 | // Handle to the transaction pools 60 | transaction::MemoryPoolList* transaction_pool(); 61 | 62 | // Get the worker ID 63 | int worker_id() const; 64 | }; 65 | 66 | 67 | /***************************************************************************** 68 | * * 69 | * Implementation details * 70 | * * 71 | *****************************************************************************/ 72 | inline 73 | gc::GarbageCollector* Worker::gc() { 74 | return m_gc; 75 | } 76 | 77 | inline 78 | transaction::MemoryPoolList* Worker::transaction_pool(){ 79 | return m_transaction_pool; 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /include/teseo/transaction/memory_pool_list.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "teseo/util/circular_array.hpp" 21 | #include "teseo/util/latch.hpp" 22 | 23 | namespace teseo::profiler { class EventThread; } // forward declaration 24 | 25 | namespace teseo::transaction { 26 | 27 | class MemoryPool; // forward declaration 28 | 29 | /** 30 | * A cache to reuse "almost empty" memory pools to create new transactions. 31 | * 32 | * This class is thread safe. 33 | */ 34 | class MemoryPoolList { 35 | MemoryPoolList(const MemoryPoolList&) = delete; 36 | MemoryPoolList& operator=(const MemoryPoolList&) = delete; 37 | 38 | util::SpinLock m_latch; // to ensure thread safety 39 | util::CircularArray m_ready; // memory pools that are ready to be reused 40 | util::CircularArray m_idle; // memory pools that are still filled 41 | profiler::EventThread* m_profiler; // internal profiler 42 | 43 | // Helper 44 | void dump_queue(const char* name, const util::CircularArray& queue) const; 45 | 46 | public: 47 | /** 48 | * Init the object 49 | */ 50 | MemoryPoolList(); 51 | 52 | /** 53 | * Destructor 54 | */ 55 | ~MemoryPoolList(); 56 | 57 | /** 58 | * Acquire a new memory pool 59 | */ 60 | MemoryPool* acquire(); 61 | 62 | /** 63 | * Release the `old' memory pool, and acquire a new one 64 | */ 65 | MemoryPool* exchange(MemoryPool* old); 66 | 67 | /** 68 | * Release the given memory pool 69 | */ 70 | void release(MemoryPool* mempool); 71 | 72 | /** 73 | * Remove from the cache the memory pools that are completely empty 74 | */ 75 | void cleanup(); 76 | 77 | /** 78 | * Reset the internal profiler 79 | */ 80 | void set_profiler(profiler::EventThread* profiler); 81 | 82 | /** 83 | * Dump the content of this class, for debugging purposes 84 | */ 85 | void dump() const; 86 | }; 87 | 88 | } // namespace 89 | -------------------------------------------------------------------------------- /include/teseo/transaction/rollback_interface.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | namespace teseo::transaction { 23 | 24 | class Undo; // forward declaration 25 | 26 | /** 27 | * Interface invoked by a transaction on a data structure to roll back a change stored in the undo 28 | * buffer. 29 | */ 30 | class RollbackInterface { 31 | public: 32 | // Destructor placeholder 33 | virtual ~RollbackInterface(); 34 | 35 | // Rollback a previously performed object 36 | // @param object the opaque item stored in the undo object, to reconstruct the change to revert 37 | // @param next the next item in the undo chain list, if anyone 38 | virtual void do_rollback(void* object, Undo* next) = 0; 39 | 40 | // Retrieve a string representation of the undo payload, for debugging purposes 41 | virtual std::string str_undo_payload(const void* object) const; 42 | }; 43 | 44 | } 45 | -------------------------------------------------------------------------------- /include/teseo/transaction/transaction_latch.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include "teseo/transaction/transaction_impl.hpp" 21 | 22 | namespace teseo::transaction { 23 | 24 | /** 25 | * This class acts as RAII object and scoped lock to the latch associated to a transaction. 26 | * It exploits an optimisation as the latch is only acquired if we know there can exist more 27 | * than one entry pointer to the transaction. 28 | */ 29 | class TransactionWriteLatch { 30 | util::OptimisticLatch<0>* m_latch; 31 | public: 32 | 33 | /** 34 | * Acquire a lock to the given transaction 35 | */ 36 | TransactionWriteLatch(const TransactionImpl* transaction); 37 | 38 | /** 39 | * Release the acquired lock 40 | */ 41 | ~TransactionWriteLatch(); 42 | }; 43 | 44 | /***************************************************************************** 45 | * * 46 | * Implementation details * 47 | * * 48 | *****************************************************************************/ 49 | inline 50 | TransactionWriteLatch::TransactionWriteLatch(const TransactionImpl* transaction) : m_latch(nullptr) { 51 | if(transaction->m_shared){ 52 | m_latch = &(transaction->m_latch); 53 | m_latch->lock(); 54 | } 55 | } 56 | 57 | inline 58 | TransactionWriteLatch::~TransactionWriteLatch(){ 59 | if(m_latch != nullptr) 60 | m_latch->unlock(); 61 | } 62 | 63 | 64 | } // namespace 65 | -------------------------------------------------------------------------------- /include/teseo/transaction/transaction_list.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include "teseo/transaction/transaction_sequence.hpp" 23 | 24 | namespace teseo::context { class GlobalContext; } // forward declaration 25 | 26 | namespace teseo::transaction { 27 | 28 | class TransactionImpl; // forward decl. 29 | 30 | /** 31 | * An ordered list of the active transactions. Each thread context owns an instance of a list 32 | * for the transactions that were created inside that context. 33 | * 34 | * To guarantee thread-safety we have a bit of protocol to follow: 35 | * - Only the local thread can invoke #insert, so there is only one writer 36 | * - The field `m_version' acts as a latch, if mod 2 == 0 => free, mod 2 = 1 => busy 37 | * - Only #insert can modify the field m_transaction_sz 38 | * - The method #remove can be invoked by any thread, it sets the related cell to nullptr 39 | * - snapshot & high_water_mark can be invoked by any thread, the field m_version will operate like an 40 | * optimistic latch on the field m_version 41 | */ 42 | class TransactionList { 43 | // This class is non copyable. 44 | TransactionList(const TransactionList&) = delete; 45 | TransactionList& operator=(const TransactionList&); 46 | 47 | std::atomic m_version = 0; // To ensure thread safety 48 | constexpr static uint64_t m_transactions_capacity = 32; // Max number of transactions that can be active inside a thread 49 | uint64_t m_transactions_sz = 0; // Number of transactions present in the list so far 50 | TransactionImpl* m_transactions[m_transactions_capacity]; // The actual list of active transactions 51 | volatile uint64_t m_highest_writer_id = 0; // The max transaction ID among the writers registered in this list 52 | 53 | public: 54 | /** 55 | * Initialise an empty transaction list 56 | */ 57 | TransactionList(); 58 | 59 | /** 60 | * Destructor 61 | */ 62 | ~TransactionList(); 63 | 64 | /** 65 | * Insert the given transaction in the list 66 | * @return the transaction id and the slot ID assigned to the transaction 67 | */ 68 | uint64_t insert(context::GlobalContext* gcntxt, TransactionImpl* transaction); 69 | 70 | /** 71 | * Remove the given transaction from the list (if present) 72 | */ 73 | bool remove(TransactionImpl* transaction); 74 | 75 | /** 76 | * Retrieve a `snapshot' of all active transactions up to this moment, sorted in 77 | * decreasing order by the transaction startTime. 78 | */ 79 | TransactionSequence snapshot(uint64_t max_transaction_id) const; 80 | 81 | /** 82 | * Retrieve the minimum transaction ID stored in the list 83 | */ 84 | uint64_t high_water_mark() const; 85 | 86 | /** 87 | * Retrieve the highest transaction ID among the read-write transactions registered in this list 88 | */ 89 | uint64_t highest_txn_rw_id() const; 90 | 91 | /** 92 | * Alias for highest_txn_rw_id, don't bother to check the latch 93 | */ 94 | uint64_t highest_txn_rw_id_unsafe() const; 95 | }; 96 | 97 | 98 | } // namespace 99 | -------------------------------------------------------------------------------- /include/teseo/transaction/transaction_sequence.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | namespace teseo::context { class GlobalContext; } // forward declaration 24 | 25 | namespace teseo::transaction { 26 | 27 | class TransactionList; // forward declaration 28 | 29 | /** 30 | * A sorted immutable sequence of transaction IDs, ordered in decreasing order by their start time 31 | */ 32 | class TransactionSequence { 33 | TransactionSequence(const TransactionSequence&) = delete; 34 | TransactionSequence& operator=(const TransactionSequence&) = delete; 35 | friend class TransactionList; 36 | friend class context::GlobalContext; 37 | 38 | uint64_t* m_transaction_ids = nullptr; // the actual sequence of transactions 39 | /*const*/ uint64_t m_num_transactions = 0; // the total number of transactions contained 40 | 41 | // Invoked by GlobalContext#active_transactions() and TransactionList#snapshot() 42 | TransactionSequence(uint64_t num_transactions); 43 | public: 44 | /** 45 | * Create an empty sequence 46 | */ 47 | TransactionSequence(); 48 | 49 | /** 50 | * Move constructor 51 | */ 52 | TransactionSequence(TransactionSequence&& move); 53 | TransactionSequence& operator=(TransactionSequence&& move); 54 | 55 | /** 56 | * Destructors 57 | */ 58 | ~TransactionSequence(); 59 | 60 | /** 61 | * Total number of transactions contained in the sequence. Some entries may be null 62 | */ 63 | uint64_t size() const; 64 | 65 | /** 66 | * Retrieve the transaction at the given position in the sequence. Some entries may be null. 67 | */ 68 | uint64_t operator[](uint64_t index) const; 69 | 70 | /** 71 | * Retrieve a string representation of the sequence, for debugging purposes 72 | */ 73 | std::string to_string() const; 74 | 75 | /** 76 | * Dump the content of the sequence to stdout, for debugging purposes 77 | */ 78 | void dump() const; 79 | }; 80 | 81 | /** 82 | * Print to the output stream the content of the sequence 83 | */ 84 | std::ostream& operator<<(std::ostream& out, const TransactionSequence& sequence); 85 | 86 | } // namespace 87 | -------------------------------------------------------------------------------- /include/teseo/transaction/undo.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | #include 20 | #include 21 | 22 | namespace teseo::transaction { 23 | 24 | class RollbackInterface; // forward decl. 25 | class TransactionImpl; // forward decl. 26 | class TransactionSequence; // forward decl. 27 | 28 | /** 29 | * Header associated to a single entry in the Undo Buffer 30 | */ 31 | class Undo { 32 | TransactionImpl* m_transaction; // transaction that performed the update 33 | RollbackInterface* m_data_structure; // pointer to the data structure when the update has been performed 34 | Undo* m_next; // pointer to the older entry in the chain 35 | const uint32_t m_length_payload; // the length, in bytes, of the payload associated to this undo record 36 | bool m_active; // whether the update is also in the data structure 37 | 38 | public: 39 | /** 40 | * Create a new Undo entry 41 | * @param tx: the transaction that is performing the update 42 | * @param data_structure: the data structure, e.g. the sparse array, where the update has been performed 43 | * @param next: pointer to the next update (undo) in the chain, possible nullptr 44 | * @param type: the type of the record stored in the update 45 | * @param length: the size of the record stored in the update 46 | */ 47 | Undo(TransactionImpl* tx, RollbackInterface* data_structure, uint32_t length); 48 | 49 | // The transaction the performed the update 50 | const TransactionImpl* transaction() const; 51 | TransactionImpl* transaction(); 52 | 53 | // The id associated to this update 54 | uint64_t transaction_id() const; 55 | 56 | // Pointer to the payload associated to this undo entry 57 | void* payload() const; 58 | 59 | // Length of the undo record & its associated payload, in bytes 60 | uint64_t length() const; 61 | 62 | // Read the next undo record in the chain 63 | Undo* next() const; 64 | 65 | // Check whether this undo record is active 66 | bool is_active() const; 67 | 68 | // Mark as active the current undo record 69 | void set_active(Undo* next); 70 | 71 | // Prune the undo chain according to the given (sorted) sequence of active transactions 72 | // Returns a pair with the new head of the chain (or nullptr) and the total length of the chain 73 | static std::pair prune(Undo* head, const TransactionSequence* sequence); 74 | 75 | // Prune the undo chain according to the given high watermark 76 | // Returns a pair with the new head of the chain (or nullptr) and the total length of the chain 77 | static std::pair prune(Undo* head, uint64_t high_water_mark); 78 | 79 | // Completely clear the chain of undos. Invoked only by the destructor of a data structure to 80 | // completely release the memory used 81 | static void clear(Undo* head); 82 | 83 | // Revert the changes of this entry 84 | void rollback(); 85 | 86 | // Get a string representation of this undo record, for debugging purposes 87 | std::string to_string() const; 88 | 89 | // Dump to stdout the content of this undo, for debugging purposes 90 | void dump() const; 91 | 92 | // Dump the whole chains of undos 93 | static void dump_chain(Undo* head, int prefix_blank_spaces = 2); 94 | }; 95 | 96 | } // namespace 97 | -------------------------------------------------------------------------------- /include/teseo/transaction/undo_buffer.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | namespace teseo::transaction { 23 | 24 | class MemoryPool; // forward decl. 25 | 26 | /** 27 | * Memory space for multiple undo records 28 | */ 29 | class UndoBuffer { 30 | UndoBuffer(const UndoBuffer&) = delete; 31 | UndoBuffer& operator=(const UndoBuffer&) = delete; 32 | friend class MemoryPool; 33 | 34 | // Init the buffer 35 | UndoBuffer(uint64_t total_space); 36 | 37 | // Destructor, limit the visibility 38 | ~UndoBuffer(); 39 | 40 | public: 41 | uint32_t m_space_left; // amount of space left in the buffer, in bytes 42 | const uint32_t m_space_total; // total amount of space in the buffer, in bytes 43 | UndoBuffer* m_next {nullptr}; // pointer to the next undo log in the chain 44 | 45 | // Access the underlying buffer 46 | const uint8_t* buffer() const; 47 | uint8_t* buffer(); 48 | 49 | // Retrieve how much space is occupied by an UndoBuffer of the given size 50 | static uint64_t undobuffer_sz(uint32_t buffer_sz); 51 | 52 | // Create a new buffer of the given size 53 | static UndoBuffer* allocate(uint32_t buffer_sz); 54 | 55 | // Deallocate the given buffer 56 | static void deallocate(UndoBuffer* undobuffer); 57 | }; 58 | 59 | /***************************************************************************** 60 | * * 61 | * Implementation details * 62 | * * 63 | *****************************************************************************/ 64 | inline 65 | UndoBuffer::UndoBuffer(uint64_t total_space) : m_space_left(total_space), m_space_total(total_space) { } 66 | 67 | inline 68 | UndoBuffer::~UndoBuffer(){ } 69 | 70 | inline 71 | const uint8_t* UndoBuffer::buffer() const{ 72 | return reinterpret_cast(this +1); 73 | } 74 | 75 | inline 76 | uint8_t* UndoBuffer::buffer() { 77 | return reinterpret_cast(this +1); 78 | } 79 | 80 | inline 81 | uint64_t UndoBuffer::undobuffer_sz(uint32_t buffer_sz){ 82 | return sizeof(UndoBuffer) + buffer_sz; 83 | } 84 | 85 | } // namespace 86 | -------------------------------------------------------------------------------- /include/teseo/util/assembly.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace teseo::util { 25 | 26 | /** 27 | * Read the cpu timestamp counter 28 | */ 29 | inline uint64_t rdtscp(){ 30 | uint64_t rax; 31 | asm volatile ( 32 | "rdtscp ; shl $32, %%rdx; or %%rdx, %%rax; " 33 | : "=a" (rax) 34 | : /* no inputs */ 35 | : "rcx", "rdx" 36 | ); 37 | return rax; 38 | } 39 | 40 | /** 41 | * Prefetch, fetch a block of memory into the local cache 42 | */ 43 | inline void prefetch(void* pointer){ 44 | __builtin_prefetch(pointer, /* 0 = read only, 1 = read/write */ 0 /*, temporal locality, the default is 3 */); 45 | } 46 | 47 | /** 48 | * Emit the instruction PAUSE, a hint for the processor that it is performing a spin loop 49 | */ 50 | inline void pause(){ 51 | _mm_pause(); 52 | } 53 | 54 | /** 55 | * Atomically load the given 128-bits variable. This is a wrapper to the instruction cmpxchg16b w/ lock. 56 | */ 57 | inline unsigned __int128 atomic_load_16(unsigned __int128& variable){ 58 | // The Intel Software Developer Manual demands that `the destination (memory) operand be 16-byte aligned.' 59 | assert(reinterpret_cast(&variable) % 16 == 0 && "The given variable is not aligned to 16 bytes"); 60 | 61 | uint64_t output_high {0}, output_low {0}; 62 | asm volatile( 63 | "lock cmpxchg16b %0 ;" 64 | /* output */ : "+m" (variable), /* rdx */ "+d" (output_high), /* rax */ "+a" (output_low) // + = read/write, = write only 65 | /* input */ : /* rcx */ "c" (0), /* rbx */ "b" (0) 66 | /* clobber */: /* flags */ "cc" 67 | ); 68 | return (static_cast(output_high) << 64) | output_low; 69 | } 70 | 71 | /** 72 | * Atomically store the given value into the 128-bits variable. This is a wrapper to the instruction cmpxchg16b w/ lock. 73 | */ 74 | inline void atomic_store_16(unsigned __int128& variable, unsigned __int128 value){ 75 | // The Intel Software Developer Manual demands that `the destination (memory) operand be 16-byte aligned.' 76 | assert(reinterpret_cast(&variable) % 16 == 0 && "The destination variable is not aligned to 16 bytes"); 77 | 78 | // Extract the 64 MSB and 64 LSB of the operands 79 | uint64_t input_high = static_cast(value >> 64); 80 | uint64_t input_low = static_cast(value); 81 | uint64_t output_high = static_cast(variable >> 64); 82 | uint64_t output_low = static_cast(variable); 83 | bool done = false; 84 | 85 | // This is a CAS instruction. The idea is that we keep testing & reloading the value of variable until we succeed. 86 | do { // cmpxchg16b: compare & exchange 87 | asm volatile( 88 | "lock cmpxchg16b %0 ;" 89 | /* output */ : "+m" (variable), "=@ccz" (done), /* rdx */ "+d" (output_high), /* rax */ "+a" (output_low) // + = read/write, = write only 90 | /* input */ : /* rcx */ "c" (input_high), /* rbx */ "b" (input_low) 91 | /* clobber */: /* flags */ "cc" 92 | ); 93 | } while(!done); 94 | } 95 | 96 | } // namespace 97 | -------------------------------------------------------------------------------- /include/teseo/util/chrono.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace teseo::util { 25 | 26 | /** 27 | * Cast a chrono::duration to a timeval 28 | */ 29 | template 30 | struct timeval duration2timeval(Duration duration){ 31 | uint64_t microseconds = std::chrono::duration_cast(duration).count(); 32 | struct timeval result; 33 | result.tv_sec = microseconds / (/* milli */ 1000 * /* micro */ 1000); 34 | result.tv_usec = microseconds % (/* milli */ 1000 * /* micro */ 1000); 35 | return result; 36 | } 37 | 38 | /** 39 | * Convert the given time point to a human readable representation 40 | */ 41 | std::string to_string(const std::chrono::time_point& tp); 42 | 43 | 44 | } // namespace 45 | -------------------------------------------------------------------------------- /include/teseo/util/compiler.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | namespace teseo::util { 21 | 22 | /** 23 | * Compiler barrier 24 | */ 25 | inline void compiler_barrier(){ 26 | __asm__ __volatile__("": : :"memory"); 27 | }; 28 | 29 | /** 30 | * Branch prediction macros 31 | */ 32 | #define LIKELY(x) __builtin_expect((x),1) 33 | #define UNLIKELY(x) __builtin_expect((x),0) 34 | 35 | } // namespace 36 | -------------------------------------------------------------------------------- /include/teseo/util/debug.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | // Internal handling 21 | //#define MAYBE_BREAK_INTO_DEBUGGER_ENABLED 22 | 23 | #include 24 | #include 25 | 26 | #include "teseo/util/thread.hpp" 27 | 28 | 29 | namespace teseo::util { 30 | 31 | /** 32 | * Get a string representation of the class & method where the macro is invoked 33 | */ 34 | #define DEBUG_WHOAMI ::teseo::util::debug_function_name(__PRETTY_FUNCTION__) 35 | 36 | /** 37 | * Print to stdout the given message, but only iff the macro DEBUG is defined 38 | */ 39 | //#define DEBUG 40 | #define COUT_DEBUG_FORCE(msg) { std::scoped_lock lock(::teseo::util::g_debugging_mutex); std::cout << "[" << DEBUG_WHOAMI << "] [" << ::teseo::util::Thread::get_thread_id() << "] " << msg << std::endl; } 41 | #if defined(DEBUG) 42 | #define COUT_DEBUG(msg) COUT_DEBUG_FORCE(msg) 43 | #else 44 | #define COUT_DEBUG(msg) 45 | #endif 46 | 47 | /** 48 | * Mutex, to avoid concurrently clogging the stdout 49 | */ 50 | extern std::mutex g_debugging_mutex; 51 | 52 | /** 53 | * Internal function to retrieve the class & function name of the given invocation 54 | */ 55 | std::string debug_function_name(const char* pretty_name); 56 | 57 | /** 58 | * Parts of the code programmatically cause to jump into the debugger when some conditions are hit, e.g. an 59 | * unexpected exception is thrown. 60 | * To enable these jumps both the macro MAYBE_BREAK_INTO_DEBUGGER_ENABLED must be statically enabled and the 61 | * global variable maybe_break_into_debugger_enabled must be set to true at runtime, using: 62 | * context::global_context()->set_break_into_debugger(true); 63 | */ 64 | #if defined(MAYBE_BREAK_INTO_DEBUGGER_ENABLED) 65 | extern bool maybe_break_into_debugger_enabled; 66 | #define MAYBE_BREAK_INTO_DEBUGGER if(::teseo::util::maybe_break_into_debugger_enabled){ ::teseo::util::break_into_debugger(); } 67 | #else 68 | #define MAYBE_BREAK_INTO_DEBUGGER 69 | #endif 70 | 71 | /** 72 | * Synchronously raise a SIGTRAP and jump the execution to the debugger 73 | */ 74 | void break_into_debugger(); 75 | 76 | } 77 | 78 | 79 | -------------------------------------------------------------------------------- /include/teseo/util/error.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #define _TESEO_INTERNAL 21 | #include "teseo.hpp" 22 | 23 | #include 24 | #include 25 | 26 | namespace teseo::util { 27 | 28 | extern std::stringstream g_exception_stream; // helper to create the exception message 29 | extern std::mutex g_exception_mutex; // mutual exclusion to create the exception message 30 | 31 | } 32 | 33 | /** 34 | * It prepares the arguments `file', `line', `function', and `what' to be passed to an exception ctor 35 | * @param msg the message stream to concatenate 36 | */ 37 | #define RAISE_EXCEPTION_CREATE_ARGUMENTS(msg) const char* file = __FILE__; int line = __LINE__; const char* function = __FUNCTION__; \ 38 | std::unique_lock lock(::teseo::util::g_exception_mutex); \ 39 | auto& stream = ::teseo::util::g_exception_stream; \ 40 | stream.str(""); stream.clear(); \ 41 | stream << msg; \ 42 | std::string what = stream.str(); \ 43 | stream.str(""); stream.clear(); /* reset once again */ 44 | 45 | /** 46 | * Raises an exception with the given message 47 | * @param exception the exception to throw 48 | * @param msg: an implicit ostream, with arguments concatenated with the symbol << 49 | */ 50 | #define RAISE_EXCEPTION(exc, msg) { RAISE_EXCEPTION_CREATE_ARGUMENTS(msg); throw exc( #exc, what, file, line, function); } 51 | #define RAISE(exc, msg) RAISE_EXCEPTION(exc, msg) 52 | 53 | 54 | /** 55 | * These exception classes are so similar, so define a general macro to create the exception 56 | */ 57 | #define DEFINE_EXCEPTION1( exceptionName, exceptionSubClass ) class exceptionName: public exceptionSubClass { \ 58 | public: exceptionName(const std::string& exceptionClass, const std::string& message, const std::string& file, \ 59 | int line, const std::string& function) : \ 60 | exceptionSubClass(exceptionClass, message, file, line, function) { } \ 61 | } /* End of DEFINE_EXCEPTION1 */ 62 | #define DEFINE_EXCEPTION0( exceptionName ) DEFINE_EXCEPTION1( exceptionName, teseo::Exception ) 63 | 64 | /** 65 | * The exception type to throw when using the macro `ERROR' 66 | */ 67 | #define CURRENT_ERROR_TYPE ::teseo::Exception 68 | 69 | /** 70 | * Helper for the macro `ERROR' to fully expand the definition CURRENT_ERROR_TYPE before 71 | * invoking RAISE_EXCEPTION 72 | */ 73 | #define _RAISE_EXCEPTION(exc, msg) RAISE_EXCEPTION(exc, msg) 74 | 75 | /** 76 | * Convenience macro, it raises an exception of type `Error'. 77 | */ 78 | #define ERROR(message) _RAISE_EXCEPTION(CURRENT_ERROR_TYPE, message) 79 | 80 | /** 81 | * Convenience shortcut to raise a VertexError 82 | */ 83 | #define VERTEX_ERROR(vertex, message) { RAISE_EXCEPTION_CREATE_ARGUMENTS(message); throw ::teseo::VertexError( vertex, "VertexError", what, file, line, function); } 84 | 85 | /** 86 | * Convenience shortcut to raise an EdgeError 87 | */ 88 | #define EDGE_ERROR(source, destination, message) { RAISE_EXCEPTION_CREATE_ARGUMENTS(message); throw ::teseo::EdgeError( source, destination, "EdgeError", what, file, line, function); } 89 | 90 | 91 | namespace teseo { 92 | 93 | /** 94 | * Any internal logical error 95 | */ 96 | DEFINE_EXCEPTION0(InternalError); 97 | 98 | } 99 | -------------------------------------------------------------------------------- /include/teseo/util/interface.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | namespace teseo::memstore { struct Error; } // forward declaration 23 | 24 | namespace teseo::util { 25 | 26 | /** 27 | * Translate an error raised by the Memstore to a more informative exception 28 | * for the user, e.g. "The Vertex 5 does not exist" 29 | */ 30 | void handle_error(const memstore::Error& error); 31 | 32 | } // namespace 33 | 34 | -------------------------------------------------------------------------------- /include/teseo/util/libevent.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | struct event; // libevent forward decl. 23 | struct event_base; // libevent forward decl. 24 | 25 | namespace teseo::util { 26 | 27 | /** 28 | * Collection of utility functions to handle and operate on libevent 29 | */ 30 | struct LibEvent { 31 | 32 | /** 33 | * Initialise the library libevent. If the library has been already initialised, this call is ignored. 34 | */ 35 | static void init(); 36 | 37 | /** 38 | * Shutdown the library libevent. This should be invoked once for each call to libevent_init(). 39 | */ 40 | static void shutdown(); 41 | 42 | /** 43 | * Collect all events still present in the libevent's queue 44 | */ 45 | static std::vector get_pending_events(struct event_base* queue); 46 | 47 | }; 48 | 49 | 50 | } // namespace 51 | -------------------------------------------------------------------------------- /include/teseo/util/numa.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | namespace teseo::util { 23 | 24 | /** 25 | * Methods to mess up with the NUMA nodes in the system 26 | */ 27 | struct NUMA { 28 | 29 | // Validate that the settings determined at compiled time for the StaticConfiguration 30 | // are still valid. In case of failure, the whole program needs to be reconfigured with 31 | // autoconf and recompiled. 32 | static void check_numa_support(); 33 | 34 | // Allocate a chunk of memory on the first node, i.e. node 0. 35 | // If numa support is not available, fall back to standard malloc 36 | static void* malloc(uint64_t size); 37 | 38 | // Allocate a chunk of memory on the given node 39 | // If numa support is not available, it will raise an exception InternalError 40 | static void* malloc(uint64_t size, int node); 41 | 42 | // Free the memory previously allocated with #numa_malloc 43 | static void free(void* pointer); 44 | 45 | // Copy the amount node previously allocated with #numa_malloc to the specific node 46 | // If numa support is disabled, it will raise an exception InternalError 47 | static void* copy(void* pointer, int node); 48 | 49 | }; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /include/teseo/util/system.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | namespace teseo::util { 23 | 24 | /** 25 | * Utility methods related to the current system 26 | */ 27 | struct System { 28 | // Retrieve the host name of the underlying machine 29 | static std::string hostname(); 30 | }; 31 | 32 | } // namespace 33 | -------------------------------------------------------------------------------- /include/teseo/util/thread.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | namespace teseo::util { 24 | 25 | /** 26 | * Utility methods to operate on threads 27 | */ 28 | struct Thread { 29 | 30 | /** 31 | * Get the Linux thread ID, that is the identifier shown by the debugger 32 | */ 33 | static int64_t get_thread_id(); 34 | 35 | /** 36 | * Get the CPU where the current thread is executing 37 | */ 38 | static int get_cpu_id(); 39 | 40 | /** 41 | * Get the NUMA node for the current thread 42 | */ 43 | static int get_numa_id(); 44 | 45 | /** 46 | * Get the process ID associated to this process 47 | */ 48 | static int64_t get_process_id(); 49 | 50 | /** 51 | * Set the name of the current thread. The given name will appear in the debugger thread list. 52 | */ 53 | static void set_name(const std::string& name); 54 | 55 | /** 56 | * Get the name of the current thread 57 | */ 58 | static std::string get_name(); 59 | 60 | }; 61 | 62 | } // namespace 63 | -------------------------------------------------------------------------------- /src/aux/cache.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #include "teseo/aux/cache.hpp" 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "teseo/aux/static_view.hpp" 24 | #include "teseo/util/latch.hpp" 25 | 26 | using namespace std; 27 | 28 | namespace teseo::aux { 29 | 30 | Cache::Cache() : m_transaction_id(0) { 31 | for(uint64_t i = 0; i < NUM_NODES; i++){ 32 | m_views[i] = nullptr; 33 | } 34 | } 35 | 36 | Cache::~Cache() { 37 | unset(); 38 | } 39 | 40 | bool Cache::get(uint64_t transaction_id, uint64_t highest_txn_rw_id, aux::StaticView** output){ 41 | util::WriteLatch xlock(m_latch); 42 | 43 | if(m_views[0] == nullptr){ // the cache is empty 44 | return false; 45 | } else if(highest_txn_rw_id > m_transaction_id){ // the cache became invalid 46 | unset(); 47 | return false; 48 | } else if(transaction_id >= m_transaction_id){ 49 | for(uint64_t i = 0; i < NUM_NODES; i++){ 50 | m_views[i]->incr_ref_count(); 51 | output[i] = m_views[i]; 52 | } 53 | 54 | return true; 55 | } else { // transaction_id < m_transaction_id 56 | return false; 57 | } 58 | } 59 | 60 | void Cache::set(aux::StaticView** views, uint64_t transaction_id){ 61 | util::WriteLatch xlock(m_latch); 62 | 63 | if(transaction_id > m_transaction_id){ 64 | unset(); 65 | 66 | for(uint64_t i = 0; i < NUM_NODES; i++){ 67 | views[i]->incr_ref_count(); 68 | m_views[i] = views[i]; 69 | } 70 | 71 | m_transaction_id = transaction_id; 72 | } 73 | } 74 | 75 | void Cache::unset(){ 76 | if(m_views[0] != nullptr){ 77 | for(uint64_t i = 0; i < NUM_NODES; i++){ 78 | m_views[i]->decr_ref_count(); 79 | m_views[i] = nullptr; 80 | } 81 | } 82 | } 83 | 84 | string Cache::to_string() const { 85 | stringstream ss; 86 | util::WriteLatch xlock(m_latch); 87 | 88 | ss << "transaction_id: " << m_transaction_id << ", views: ["; 89 | for(uint64_t i = 0; i < NUM_NODES; i++){ 90 | if(i > 0) ss << ", "; 91 | ss << m_views[i]; 92 | } 93 | ss << "]"; 94 | 95 | 96 | return ss.str(); 97 | } 98 | 99 | void Cache::dump() const { 100 | cout << "[Cache] " << to_string() << endl; 101 | } 102 | 103 | ostream& operator<<(ostream& out, const Cache& cache){ 104 | out << cache.to_string(); 105 | return out; 106 | } 107 | 108 | } // namespace 109 | -------------------------------------------------------------------------------- /src/aux/cb_serialise_build.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #include "teseo/aux/cb_serialise_build.hpp" 18 | 19 | using namespace std; 20 | 21 | namespace teseo::aux { 22 | 23 | CbSerialiseBuild::CbSerialiseBuild() : m_done(false) { } 24 | 25 | CbSerialiseBuild::~CbSerialiseBuild(){ } 26 | 27 | void CbSerialiseBuild::done(){ 28 | m_mutex.lock(); 29 | m_done = true; 30 | m_mutex.unlock(); 31 | m_condvar.notify_all(); 32 | } 33 | 34 | void CbSerialiseBuild::wait(){ 35 | unique_lock xlock(m_mutex); 36 | m_condvar.wait(xlock, [this]{ return m_done == true; }); 37 | } 38 | 39 | } // namespace 40 | -------------------------------------------------------------------------------- /src/aux/item.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/aux/item.hpp" 19 | 20 | #include 21 | #include 22 | 23 | using namespace std; 24 | 25 | namespace teseo::aux { 26 | 27 | string ItemUndirected::to_string() const { 28 | stringstream ss; 29 | ss << "vertex id: " << m_vertex_id << ", degree: " << m_degree; 30 | return ss.str(); 31 | } 32 | 33 | ostream& operator<<(ostream& out, const ItemUndirected& item){ 34 | out << item.to_string(); 35 | return out; 36 | } 37 | 38 | } // namespace 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/aux/partial_result.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/aux/partial_result.hpp" 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "teseo/aux/builder.hpp" 25 | #include "teseo/context/static_configuration.hpp" 26 | #include "teseo/memstore/key.hpp" 27 | 28 | #include "teseo/util/debug.hpp" 29 | 30 | using namespace std; 31 | 32 | namespace teseo::aux { 33 | 34 | PartialResult::PartialResult(Builder* builder, uint64_t id, const memstore::Key& from, const memstore::Key& to) : 35 | m_builder(builder), m_id(id), m_from(from), m_to(to), m_array(nullptr), m_last(-1), m_capacity(0) 36 | { 37 | static_assert(context::StaticConfiguration::aux_partial_init_capacity > 0); 38 | resize(context::StaticConfiguration::aux_partial_init_capacity); 39 | assert(capacity() > 0 && "Error in the resize"); 40 | } 41 | 42 | PartialResult::~PartialResult(){ 43 | delete[] m_array; m_array = nullptr; 44 | m_capacity = 0; 45 | } 46 | 47 | void PartialResult::resize(uint64_t new_capacity){ 48 | ItemUndirected* new_array = new ItemUndirected[new_capacity](); 49 | memcpy((void*) new_array, m_array, size() * sizeof(new_array[0])); 50 | delete[] m_array; 51 | m_array = new_array; 52 | m_capacity = new_capacity; 53 | } 54 | 55 | void PartialResult::incr_degree(uint64_t vertex_id, uint64_t increment){ 56 | if(!empty() && m_array[m_last].m_vertex_id == vertex_id){ 57 | m_array[m_last].m_degree += increment; 58 | } else { // m_array[m_last].first != vertex_id 59 | if(size() == capacity()) resize(capacity() * 2); 60 | assert((m_last < 0 || m_array[m_last].m_vertex_id < vertex_id) && "Sorted order not respected"); 61 | m_last++; 62 | m_array[m_last].m_vertex_id = vertex_id; 63 | m_array[m_last].m_degree = increment; 64 | } 65 | } 66 | 67 | void PartialResult::done(){ 68 | m_builder->collect(this); 69 | } 70 | 71 | uint64_t PartialResult::id() const noexcept { 72 | return m_id; 73 | } 74 | 75 | const memstore::Key& PartialResult::key_from() const noexcept { 76 | return m_from; 77 | } 78 | 79 | const memstore::Key& PartialResult::key_to() const noexcept { 80 | return m_to; 81 | } 82 | 83 | uint64_t PartialResult::capacity() const noexcept { 84 | return m_capacity; 85 | } 86 | 87 | uint64_t PartialResult::size() const noexcept { 88 | return m_last +1; 89 | } 90 | 91 | bool PartialResult::empty() const noexcept { 92 | return size() == 0; 93 | } 94 | 95 | const ItemUndirected& PartialResult::get(uint64_t index) const { 96 | assert(index < size() && "Overflow"); 97 | return m_array[index]; 98 | } 99 | 100 | const ItemUndirected& PartialResult::at(uint64_t index) const { 101 | return get(index); 102 | } 103 | 104 | void PartialResult::dump() const { 105 | cout << "[PartialResult] id: " << id() << ", interval: [" << key_from() << ", " << key_to() << "), size: " << size() << ", capacity: " << capacity() << "\n"; 106 | for(uint64_t i = 0, end = size(); i < end; i++){ 107 | cout << "[" << i << "] vertex id: " << at(i).m_vertex_id << ", degree: " << at(i).m_degree << "\n"; 108 | } 109 | flush(cout); 110 | } 111 | 112 | } // namespace 113 | -------------------------------------------------------------------------------- /src/aux/view.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/aux/view.hpp" 19 | 20 | #include 21 | 22 | #include "teseo/aux/dynamic_view.hpp" 23 | #include "teseo/aux/static_view.hpp" 24 | #include "teseo/context/scoped_epoch.hpp" 25 | #include "teseo/util/error.hpp" 26 | #include "teseo/util/numa.hpp" 27 | 28 | namespace teseo::aux { 29 | 30 | View::View(bool is_static) : m_is_static(is_static) { 31 | 32 | } 33 | 34 | View::~View(){ 35 | 36 | } 37 | 38 | uint64_t View::vertex_id(uint64_t logical_id) const noexcept { 39 | if(m_is_static){ 40 | return reinterpret_cast(this)->vertex_id(logical_id); 41 | } else { 42 | return reinterpret_cast(this)->vertex_id(logical_id); 43 | } 44 | } 45 | 46 | uint64_t View::logical_id(uint64_t vertex_id) const noexcept { 47 | if(m_is_static){ 48 | return reinterpret_cast(this)->logical_id(vertex_id); 49 | } else { 50 | return reinterpret_cast(this)->logical_id(vertex_id); 51 | } 52 | } 53 | 54 | uint64_t View::degree(uint64_t id, bool is_logical) const noexcept { 55 | if(m_is_static){ 56 | return reinterpret_cast(this)->degree(id, is_logical); 57 | } else { 58 | return reinterpret_cast(this)->degree(id, is_logical); 59 | } 60 | } 61 | 62 | uint64_t View::num_vertices() const noexcept { 63 | if(m_is_static){ 64 | return reinterpret_cast(this)->num_vertices(); 65 | } else { 66 | return reinterpret_cast(this)->num_vertices(); 67 | } 68 | } 69 | 70 | void View::incr_ref_count() noexcept { 71 | m_ref_count++; 72 | } 73 | 74 | void View::decr_ref_count() noexcept { 75 | if(--m_ref_count == 0){ 76 | this->~View(); 77 | util::NUMA::free(this); 78 | } 79 | } 80 | 81 | } // namespace 82 | -------------------------------------------------------------------------------- /src/context/tc_list.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #include "teseo/context/tc_list.hpp" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "teseo/context/global_context.hpp" 25 | #include "teseo/context/static_configuration.hpp" 26 | #include "teseo/gc/garbage_collector.hpp" 27 | 28 | using namespace std; 29 | 30 | namespace teseo::context { 31 | 32 | TcList::TcList(GlobalContext* global_context) : m_global_context(global_context), m_list(nullptr), m_size(0), m_capacity(StaticConfiguration::context_tclist_initial_capacity -1){ 33 | m_list = (ThreadContext**) calloc(sizeof(ThreadContext*), m_capacity +1); 34 | if(m_list == nullptr) throw std::bad_alloc{}; 35 | } 36 | 37 | TcList::~TcList(){ 38 | free(m_list); m_list = nullptr; 39 | } 40 | 41 | void TcList::resize(){ 42 | uint32_t new_capacity = (m_capacity +1) * 2; 43 | ThreadContext** new_list = (ThreadContext**) calloc(sizeof(ThreadContext*), new_capacity); 44 | if(new_list == nullptr) throw std::bad_alloc{}; 45 | memcpy(new_list, m_list, m_size * sizeof(ThreadContext*)); 46 | m_global_context->gc()->mark(m_list, free); 47 | m_list = new_list; 48 | m_capacity = new_capacity -1; // 64 -> 63, last position is a marker with a nullptr 49 | } 50 | 51 | void TcList::insert(ThreadContext* thread_context){ 52 | scoped_lock> xlock(m_latch); 53 | if(m_size == capacity()) resize(); 54 | assert(m_size < capacity() && "The list is full"); 55 | m_list[m_size] = thread_context; 56 | m_size++; 57 | } 58 | 59 | void TcList::remove(ThreadContext* thread_context){ 60 | // atb it is safer to acquire the latch in the global context. Otherwise the logic needs to be 61 | // readjusted a bit to move the xlock here. 62 | //scoped_lock> xlock(m_latch); 63 | assert(m_latch.is_locked() && "It should have been acquired in the global context"); 64 | 65 | ThreadContext** __restrict tc_list = m_list; 66 | uint32_t pos = 0; 67 | uint32_t size = m_size; 68 | 69 | while(pos < size && tc_list[pos] != thread_context) pos++; 70 | assert(pos < size && "Thread context not found"); 71 | // shift the existing elements to the left 72 | while(pos < size){ tc_list[pos] = tc_list[pos +1]; pos++; } /* let it overflow at size+1, it will copy nullptr */ 73 | m_size = size - 1; 74 | } 75 | 76 | uint32_t TcList::capacity() const { 77 | return m_capacity; 78 | } 79 | 80 | } // namespace 81 | 82 | -------------------------------------------------------------------------------- /src/gc/item.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/gc/item.hpp" 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "teseo/util/assembly.hpp" 28 | 29 | //#define DEBUG 30 | #include "teseo/util/debug.hpp" 31 | 32 | using namespace std; 33 | 34 | namespace teseo::gc { 35 | 36 | 37 | Item::Item() : m_timestamp(0), m_pointer(nullptr), m_deleter(free){ 38 | 39 | } 40 | 41 | 42 | Item::Item(void* pointer, void (*deleter)(void*)) : m_timestamp(util::rdtscp()), m_pointer(pointer), m_deleter(deleter) { 43 | assert(deleter != nullptr); 44 | } 45 | 46 | void* Item::pointer() const { 47 | return m_pointer; 48 | } 49 | 50 | void Item::process(){ 51 | COUT_DEBUG("item: " << *this); 52 | m_deleter(m_pointer); 53 | m_pointer = nullptr; 54 | } 55 | 56 | bool Item::process_if(uint64_t epoch){ 57 | if(m_timestamp < epoch){ 58 | process(); 59 | return true; 60 | } else { 61 | return false; 62 | } 63 | } 64 | 65 | string Item::to_string() const { 66 | stringstream ss; 67 | ss << "timestamp: " << m_timestamp << ", pointer: " << m_pointer << ", deleter: " << m_deleter; 68 | return ss.str(); 69 | } 70 | 71 | ostream& operator<<(ostream& out, const Item& item){ 72 | out << item.to_string(); 73 | return out; 74 | } 75 | 76 | } // namespace 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/gc/tc_queue.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/gc/tc_queue.hpp" 19 | 20 | #include 21 | 22 | #include "teseo/context/static_configuration.hpp" 23 | #include "teseo/gc/garbage_collector.hpp" 24 | #include "teseo/gc/item.hpp" 25 | #include "teseo/gc/simple_queue.hpp" 26 | #include "teseo/util/thread.hpp" 27 | 28 | //#define DEBUG 29 | #include "teseo/util/debug.hpp" 30 | 31 | namespace teseo::gc { 32 | 33 | TcQueue::TcQueue(GarbageCollector* gc) : m_local( new SimpleQueue() ), m_shared( gc->create_shared_queue() ), m_gc (gc) 34 | #if !defined(NDEBUG) 35 | , m_thread_id(util::Thread::get_thread_id()) 36 | #endif 37 | { 38 | 39 | } 40 | 41 | TcQueue::~TcQueue(){ 42 | release(); 43 | } 44 | 45 | void TcQueue::mark(void* pointer, void (*deleter)(void*)){ 46 | COUT_DEBUG("pointer: " << pointer); 47 | 48 | // Invoking the local GC is not thread safe and must be done only inside the same thread owning this queue 49 | assert(m_thread_id == util::Thread::get_thread_id() && "Attempting to invoke the local GC from another thread"); 50 | 51 | // Try to flush the local queue, as far as possible 52 | bool success = true; 53 | int num_elts_flushed = 0; 54 | int sz = m_local->size(); 55 | while(num_elts_flushed < sz && success){ 56 | Item& item = m_local->get(num_elts_flushed); 57 | success = m_shared->push(item); 58 | num_elts_flushed += success; 59 | } 60 | m_local->pop(num_elts_flushed); 61 | 62 | // Finally, mark the object we are supposed to delete either in the shared or in the local queue 63 | Item item { pointer, deleter }; 64 | success = false; 65 | if(m_local->empty()){ 66 | success = m_shared->push(item); 67 | } 68 | if(!success){ 69 | success = m_local->push(item); 70 | if(!success){ 71 | m_local->resize(); 72 | m_local->push(item); 73 | } 74 | } 75 | } 76 | 77 | void TcQueue::release(){ 78 | if(m_local != nullptr){ 79 | m_gc->unregister(m_local, m_shared); 80 | m_local = m_shared = nullptr; 81 | } 82 | } 83 | 84 | 85 | } // namespace 86 | 87 | 88 | -------------------------------------------------------------------------------- /src/memstore/cursor_state.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/memstore/cursor_state.hpp" 19 | 20 | #include 21 | #include 22 | 23 | #include "teseo/memstore/key.hpp" 24 | #include "teseo/memstore/segment.hpp" 25 | 26 | using namespace std; 27 | 28 | namespace teseo::memstore { 29 | 30 | CursorState::CursorState() : m_key(KEY_MIN) { 31 | 32 | } 33 | 34 | CursorState::~CursorState(){ 35 | close(); 36 | } 37 | 38 | void CursorState::invalidate() noexcept { 39 | m_key = KEY_MIN; 40 | } 41 | 42 | void CursorState::close() noexcept { 43 | if(is_valid()){ 44 | m_position.segment()->reader_exit(); 45 | invalidate(); 46 | } 47 | } 48 | 49 | string CursorState::to_string() const { 50 | stringstream ss; 51 | ss << "cursor"; 52 | if(!is_valid()){ 53 | ss << ", closed"; 54 | } else { 55 | ss << ", open, key: " << m_key << ", position: " << m_position; 56 | 57 | } 58 | return ss.str(); 59 | } 60 | 61 | void CursorState::dump() const { 62 | cout << "[CursorState] " << to_string() << "\n"; 63 | } 64 | 65 | ostream& operator<<(ostream& out, const CursorState& bookmark) { 66 | out << bookmark.to_string(); 67 | return out; 68 | } 69 | 70 | } // namespace 71 | -------------------------------------------------------------------------------- /src/memstore/latch_state.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/memstore/latch_state.hpp" 19 | 20 | #include 21 | 22 | #include "teseo/memstore/segment.hpp" 23 | 24 | using namespace std; 25 | 26 | namespace teseo::memstore { 27 | 28 | LatchState::LatchState(uint64_t latch) : 29 | m_invalid( (latch & Segment::MASK_INVALID) != 0 ), 30 | m_xlock ( (latch & Segment::MASK_XLOCK) != 0 ), 31 | m_writer ( (latch & Segment::MASK_WRITER) != 0 ), 32 | m_rebalancer ( (latch & Segment::MASK_REBALANCER) != 0 ), 33 | m_wait ( (latch & Segment::MASK_WAIT) != 0 ), 34 | m_readers( (latch & Segment::MASK_READERS) >> __builtin_ctzl(Segment::MASK_READERS)), 35 | m_version ( latch & Segment::MASK_VERSION ){ } 36 | 37 | string LatchState::to_string() const { 38 | stringstream ss; 39 | if(m_invalid) { ss << "invalid, "; } 40 | if(m_xlock){ ss << "xlock, "; } 41 | if(m_writer){ ss << "writer, "; } 42 | if(m_rebalancer){ ss << "rebalancer, "; } 43 | if(m_wait){ ss << "wait, "; } 44 | if(m_readers != 0){ ss << "readers(" << m_readers << "), "; } 45 | ss << "version: " << m_version; 46 | return ss.str(); 47 | } 48 | 49 | ostream& operator<<(ostream& out, const LatchState& ls){ 50 | out << ls.to_string(); 51 | return out; 52 | } 53 | 54 | } // namespace 55 | -------------------------------------------------------------------------------- /src/profiler/event_global.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/profiler/event_global.hpp" 19 | 20 | #include 21 | #include 22 | 23 | #include "teseo/profiler/event_thread.hpp" 24 | #include "teseo/util/chrono.hpp" 25 | #include "teseo/util/thread.hpp" 26 | 27 | 28 | using namespace std; 29 | using namespace std::chrono; 30 | 31 | namespace teseo::profiler { 32 | 33 | EventGlobal::EventGlobal() : m_time_ctor(system_clock::now()){ 34 | 35 | } 36 | 37 | EventGlobal::~EventGlobal(){ 38 | for(uint64_t i = 0; i < m_event_threads.size(); i++){ 39 | delete m_event_threads[i]; m_event_threads[i] = nullptr; 40 | } 41 | } 42 | 43 | void EventGlobal::acquire(EventThread* ev_thread){ 44 | ev_thread->close(); 45 | util::WriteLatch lock(m_latch); 46 | m_event_threads.push_back(ev_thread); 47 | } 48 | 49 | 50 | void EventGlobal::to_json(std::ostream& out) const { 51 | out << "{"; 52 | out << "\"start_time\": \"" << util::to_string(m_time_ctor) << "\", "; 53 | out << "\"end_time\": \"" << util::to_string(system_clock::now()) << "\", "; 54 | out << "\"thread_id\": " << util::Thread::get_thread_id() << ", "; 55 | out << "\"thread_name\": \"" << util::Thread::get_name() << "\", "; 56 | out << "\"thread_events\": [ "; 57 | bool first = true; 58 | for(uint64_t i = 0; i < m_event_threads.size(); i++){ 59 | if(m_event_threads[i]->has_events()){ 60 | if(!first) out << ", "; 61 | m_event_threads[i]->to_json(out); 62 | first = false; 63 | } 64 | } 65 | out << "]"; 66 | out << "}"; 67 | } 68 | 69 | } // namespace 70 | 71 | 72 | -------------------------------------------------------------------------------- /src/profiler/event_thread.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #include "teseo/profiler/event_thread.hpp" 18 | 19 | #include 20 | 21 | #include "teseo/util/chrono.hpp" 22 | #include "teseo/util/thread.hpp" 23 | 24 | using namespace std; 25 | using namespace std::chrono; 26 | 27 | namespace teseo::profiler { 28 | 29 | EventThread::EventThread() : m_event_list(){ 30 | m_time_ctor = system_clock::now(); 31 | m_thread_id = util::Thread::get_thread_id(); 32 | m_thread_name = util::Thread::get_name(); 33 | } 34 | 35 | void EventThread::close() { 36 | m_time_dtor = system_clock::now(); 37 | } 38 | 39 | bool EventThread::has_events() const{ 40 | for(uint64_t i = 0; i < m_event_list.size(); i++){ 41 | if(m_event_list[i].m_num_invocations > 0){ 42 | return true; 43 | } 44 | } 45 | 46 | return false; 47 | } 48 | 49 | void EventThread::to_json(std::ostream& out) const { 50 | out << "{"; 51 | out << "\"thread_id\": " << m_thread_id << ", "; 52 | out << "\"thread_name\": \"" << m_thread_name << "\", "; 53 | out << "\"start_time\": \"" << util::to_string(m_time_ctor) << "\", "; 54 | out << "\"end_time\": \"" << util::to_string(m_time_dtor) << "\", "; 55 | out << "\"events\": ["; 56 | bool first = true; 57 | 58 | for(uint64_t i = 0; i < m_event_list.size(); i++){ 59 | const EventData& event = m_event_list[i]; 60 | 61 | if(event.m_num_invocations > 0){ 62 | if(!first) out << ", "; 63 | 64 | out << "{"; 65 | out << "\"event\": \"" << magic_enum::enum_name((EventName) i) << "\", "; 66 | out << "\"microseconds\": " << duration_cast(event.m_total_time).count() << ", "; 67 | out << "\"num_created\": " << event.m_num_scoped_timers << ", "; 68 | out << "\"num_invoked\": " << event.m_num_invocations; 69 | out << "}"; 70 | 71 | first = false; 72 | } 73 | } 74 | 75 | out << "]"; 76 | 77 | out << "}"; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/profiler/rebal_global_list.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/profiler/rebal_global_list.hpp" 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "teseo/profiler/rebal_list.hpp" 25 | #include "teseo/third-party/magic_enum.hpp" 26 | 27 | using namespace std; 28 | 29 | namespace teseo::profiler { 30 | 31 | 32 | GlobalRebalanceList::GlobalRebalanceList() : m_lists(), m_num_threads() { 33 | 34 | } 35 | 36 | void GlobalRebalanceList::insert(const RebalanceList* list){ 37 | if(list == nullptr) return; 38 | util::WriteLatch lock(m_latch); 39 | m_num_threads[ (int) list->thread_type() ]++; 40 | m_lists[ (int) list->thread_type() ].insert(list); 41 | } 42 | 43 | static void to_json0(ostream& out, vector& vect){ 44 | for(uint64_t i = 0; i < vect.size(); i++){ 45 | if (i > 0) out << ", "; 46 | vect[i].to_json(out); 47 | } 48 | } 49 | 50 | void GlobalRebalanceList::to_json(std::ostream& out){ 51 | out << "["; 52 | for(uint64_t i = 0; i < m_lists.size(); i++){ 53 | RebalanceCompleteStatistics statistics = m_lists[i].statistics(); 54 | 55 | if(i > 0) out << ", "; 56 | out << "{"; 57 | 58 | ThreadType type = (ThreadType) i; 59 | out << "\"role\": \"" << magic_enum::enum_name(type) << "\", "; 60 | out << "\"num_threads\": " << m_num_threads[i] << ", "; 61 | out << "\"count\":" << statistics.m_count << ", "; 62 | out << "\"total_time\":"; statistics.m_total_time.to_json(out); out << ", "; 63 | out << "\"load_time\":"; statistics.m_load_time.to_json(out); out << ", "; 64 | out << "\"write_time\":"; statistics.m_write_time.to_json(out); out << ", "; 65 | 66 | out << "\"rebalances\": ["; to_json0(out, statistics.m_rebalances); out << "], "; 67 | out << "\"splits\": ["; to_json0(out, statistics.m_splits); out << "], "; 68 | out << "\"merges\": ["; to_json0(out, statistics.m_merges); out << "] "; 69 | 70 | out << "}"; 71 | } 72 | 73 | out << "]"; 74 | }; 75 | 76 | } // namespace 77 | -------------------------------------------------------------------------------- /src/profiler/rebal_profiler.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/profiler/rebal_profiler.hpp" 19 | 20 | #include 21 | #include 22 | 23 | #include "teseo/context/thread_context.hpp" 24 | #include "teseo/profiler/rebal_list.hpp" 25 | #include "teseo/rebalance/plan.hpp" 26 | 27 | using namespace std; 28 | using namespace std::chrono; 29 | 30 | namespace teseo::profiler { 31 | 32 | #if defined(HAVE_PROFILER) 33 | 34 | RebalanceProfiler::RebalanceProfiler(const rebalance::Plan& plan) : m_time_created(steady_clock::now()) { 35 | m_fields.m_window_length = plan.num_output_segments(); 36 | if(plan.is_rebalance()){ 37 | m_fields.m_type = RebalanceType::REBALANCE; 38 | } else if(plan.is_merge()){ 39 | m_fields.m_type = RebalanceType::MERGE; 40 | } else { 41 | assert(plan.is_resize()); 42 | m_fields.m_type = RebalanceType::SPLIT; 43 | } 44 | } 45 | 46 | RebalanceProfiler::~RebalanceProfiler(){ 47 | m_fields.m_total_time = steady_clock::now() - m_time_created; 48 | context::thread_context()->profiler_rebalances()->insert(m_fields); 49 | } 50 | 51 | void RebalanceProfiler::set_window_length(uint64_t num_segments){ 52 | m_fields.m_window_length = num_segments; 53 | } 54 | 55 | #endif 56 | 57 | } // namespace 58 | 59 | -------------------------------------------------------------------------------- /src/profiler/rebal_stats.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/profiler/rebal_stats.hpp" 19 | 20 | #include 21 | 22 | using namespace std; 23 | 24 | namespace teseo::profiler { 25 | 26 | void RebalanceFieldStatistics::to_json(ostream& out) { 27 | out << "{"; 28 | out << "\"count\": " << m_count << ", "; 29 | out << "\"sum\": " << m_sum << ", "; 30 | out << "\"mean\": " << m_average << ", "; 31 | out << "\"median\": " << m_median << ", "; 32 | out << "\"min\": " << m_min << ", "; 33 | out << "\"max\": " << m_max << ", "; 34 | out << "\"stddev\": " << m_stddev; 35 | out << "}"; 36 | } 37 | 38 | void RebalanceWindowStatistics::to_json(ostream& out){ 39 | out << "{"; 40 | out << "\"window_length\": " << m_window_length << ", "; 41 | out << "\"count\": " << m_count << ", "; 42 | out << "\"total_time\": "; m_total_time.to_json(out); out << ", "; 43 | out << "\"load_time\": "; m_load_time.to_json(out); out << ", "; 44 | out << "\"write_time\": "; m_write_time.to_json(out); out << ", "; 45 | out << "\"prune_time\": "; m_prune_time.to_json(out); out << ", "; 46 | out << "\"in_num_qwords\": "; m_in_num_qwords.to_json(out); out << ", "; 47 | out << "\"in_num_elts\": "; m_in_num_elts.to_json(out); out << ", "; 48 | out << "\"in_num_vertices\": "; m_in_num_vertices.to_json(out); out << ", "; 49 | out << "\"in_num_edges\": "; m_in_num_edges.to_json(out); out << ", "; 50 | out << "\"out_num_qwords\": "; m_out_num_qwords.to_json(out); out << ", "; 51 | out << "\"out_num_elts\": "; m_out_num_elts.to_json(out); out << ", "; 52 | out << "\"out_num_vertices\": "; m_out_num_vertices.to_json(out); out << ", "; 53 | out << "\"out_num_edges\": "; m_out_num_edges.to_json(out); //out << ", "; 54 | out << "}"; 55 | } 56 | 57 | } // namespace 58 | 59 | -------------------------------------------------------------------------------- /src/profiler/save_to_disk.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/profiler/save_to_disk.hpp" 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "teseo/profiler/event_global.hpp" 26 | #include "teseo/profiler/rebal_global_list.hpp" 27 | #include "teseo/util/chrono.hpp" 28 | #include "teseo/util/system.hpp" 29 | #include "teseo/util/thread.hpp" 30 | 31 | using namespace std; 32 | 33 | namespace teseo::profiler { 34 | 35 | void save_to_disk(EventGlobal* global_events, GlobalRebalanceList* rebalance_events){ 36 | // where to save the content 37 | string path = "/tmp/teseo-profdata-"; 38 | path += to_string(util::Thread::get_process_id()); 39 | path += ".json"; 40 | 41 | fstream out(path, ios::out); 42 | bool first = true; 43 | 44 | out << "{"; 45 | out << "\"version\": 200429, "; 46 | out << "\"hostname\": \"" << util::System::hostname() << "\", "; 47 | out << "\"date\": \"" << util::to_string(chrono::system_clock::now()) << "\", "; 48 | 49 | if(global_events != nullptr){ 50 | if(!first) { out << ", "; } 51 | 52 | out << "\"events\":"; 53 | global_events->to_json(out); 54 | 55 | first = false; 56 | } 57 | 58 | if(rebalance_events != nullptr){ 59 | if(!first) { out << ", "; } 60 | 61 | out << "\"rebalances\":"; 62 | rebalance_events->to_json(out); 63 | 64 | first = false; 65 | } 66 | 67 | out << "}"; 68 | 69 | out.close(); 70 | 71 | cout << "[TESEO] Profiler data saved to: " << path << endl; 72 | } 73 | 74 | } // namespace 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/profiler/scoped_timer.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/profiler/scoped_timer.hpp" 19 | 20 | #include "teseo/context/thread_context.hpp" 21 | #include "teseo/profiler/event_global.hpp" 22 | #include "teseo/profiler/event_thread.hpp" 23 | #include "teseo/util/compiler.hpp" 24 | 25 | using namespace std; 26 | 27 | namespace teseo::profiler { 28 | 29 | #if defined(HAVE_PROFILER) 30 | 31 | ScopedTimer::ScopedTimer(EventName event, bool start_immediately) : ScopedTimer(event, context::thread_context()->profiler_events(), start_immediately){ 32 | 33 | } 34 | 35 | ScopedTimer::ScopedTimer(EventName event, EventThread* evthread, bool start_immediately) : m_event(nullptr){ 36 | if(LIKELY(evthread != nullptr)){ 37 | m_event = evthread->get_event(event); 38 | m_event->m_num_scoped_timers++; 39 | if(start_immediately) start(); 40 | } 41 | } 42 | 43 | 44 | ScopedTimer::~ScopedTimer(){ 45 | if(LIKELY(m_event != nullptr)){ 46 | stop(); 47 | m_event->m_total_time += m_timer.duration(); 48 | } 49 | } 50 | 51 | void ScopedTimer::start(){ 52 | if(LIKELY(m_event != nullptr)){ 53 | m_event->m_num_invocations++; 54 | m_timer.resume(); 55 | } 56 | } 57 | 58 | void ScopedTimer::stop(){ 59 | if(LIKELY(m_event != nullptr)){ 60 | m_timer.stop(); 61 | } 62 | } 63 | 64 | #endif 65 | 66 | } // namespace 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/rebalance/rebalance.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/rebalance/rebalance.hpp" 19 | 20 | #include "teseo/context/scoped_epoch.hpp" 21 | #include "teseo/memstore/context.hpp" 22 | #include "teseo/memstore/key.hpp" 23 | #include "teseo/memstore/segment.hpp" 24 | #include "teseo/profiler/scoped_timer.hpp" 25 | #include "teseo/rebalance/crawler.hpp" 26 | #include "teseo/rebalance/merge_operator.hpp" 27 | #include "teseo/rebalance/plan.hpp" 28 | #include "teseo/rebalance/scratchpad.hpp" 29 | #include "teseo/rebalance/spread_operator.hpp" 30 | 31 | //#define DEBUG 32 | #include "teseo/util/debug.hpp" 33 | 34 | namespace teseo::rebalance { 35 | 36 | void handle_rebalance(memstore::Memstore* memstore, memstore::Key& key) { 37 | profiler::ScopedTimer profiler { profiler::ARS_HANDLE_REQUEST }; 38 | COUT_DEBUG("Key: " << key); 39 | context::ScopedEpoch epoch; // protect from the GC 40 | 41 | try { 42 | memstore::Context context { memstore }; 43 | Crawler crawler { context, key }; 44 | Plan plan = crawler.make_plan(); 45 | ScratchPad scratchpad { plan.cardinality_ub() }; 46 | SpreadOperator rebalance { context, scratchpad, plan }; 47 | rebalance(); 48 | } catch (Abort) { 49 | /* nop */ 50 | } catch (RebalanceNotNecessary){ 51 | /* nop */ 52 | } 53 | } 54 | 55 | } // namespace 56 | -------------------------------------------------------------------------------- /src/rebalance/weighted_edge.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/rebalance/weighted_edge.hpp" 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "teseo/memstore/data_item.hpp" 25 | 26 | using namespace std; 27 | 28 | namespace teseo::rebalance { 29 | 30 | string WeightedEdge::to_string(const memstore::Vertex* source, const memstore::Version* version) const { 31 | stringstream ss; 32 | ss << "Edge " << source->m_vertex_id << " -> " << m_destination << ", weight: " << m_weight; 33 | if(version != nullptr){ 34 | ss << ", " << version->to_string(); 35 | } 36 | return ss.str(); 37 | } 38 | 39 | } // namespace 40 | -------------------------------------------------------------------------------- /src/runtime/task.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/runtime/task.hpp" 19 | 20 | #include 21 | 22 | #include "teseo/third-party/magic_enum.hpp" 23 | 24 | using namespace std; 25 | 26 | namespace teseo::runtime { 27 | 28 | string Task::to_string() const { 29 | stringstream ss; 30 | ss << "Task: " << magic_enum::enum_name(type()) << ", payload: " << payload() << ""; 31 | return ss.str(); 32 | } 33 | 34 | ostream& operator<<(ostream& out, const Task& task){ 35 | out << task.to_string();; 36 | return out; 37 | } 38 | 39 | } // namespace 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/transaction/rollback_interface.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/transaction/rollback_interface.hpp" 19 | 20 | using namespace std; 21 | 22 | namespace teseo::transaction { 23 | 24 | RollbackInterface::~RollbackInterface(){ } 25 | 26 | string RollbackInterface::str_undo_payload(const void* object) const { 27 | return "?"; 28 | } 29 | 30 | } // namespace 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/transaction/transaction_sequence.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/transaction/transaction_sequence.hpp" 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | using namespace std; 26 | 27 | namespace teseo::transaction { 28 | 29 | TransactionSequence::TransactionSequence(): m_num_transactions(0) { } 30 | 31 | TransactionSequence::TransactionSequence(uint64_t num_transactions) : m_num_transactions(num_transactions){ 32 | m_transaction_ids = new uint64_t[m_num_transactions](); 33 | } 34 | 35 | TransactionSequence::TransactionSequence(TransactionSequence&& move) : 36 | m_transaction_ids(move.m_transaction_ids), m_num_transactions(move.m_num_transactions){ 37 | move.m_num_transactions = 0; 38 | move.m_transaction_ids = nullptr; 39 | } 40 | 41 | TransactionSequence& TransactionSequence::operator=(TransactionSequence&& move) { 42 | if(this != &move){ 43 | delete[] m_transaction_ids; 44 | m_transaction_ids = move.m_transaction_ids; 45 | m_num_transactions = move.m_num_transactions; 46 | 47 | move.m_num_transactions = 0; 48 | move.m_transaction_ids = nullptr; 49 | } 50 | return *this; 51 | } 52 | 53 | TransactionSequence::~TransactionSequence() { 54 | delete[] m_transaction_ids; m_transaction_ids = nullptr; 55 | } 56 | 57 | uint64_t TransactionSequence::size() const { 58 | return m_num_transactions; 59 | } 60 | 61 | uint64_t TransactionSequence::operator[](uint64_t index) const { 62 | assert(index < size()); 63 | return m_transaction_ids[index]; 64 | } 65 | 66 | string TransactionSequence::to_string() const { 67 | stringstream ss; 68 | if(size() == 0){ 69 | ss << "empty"; 70 | } else { 71 | ss << "["; 72 | for(uint64_t i = 0, sz = size(); i < sz; i++){ 73 | if(i > 0) ss << ", "; 74 | ss << (*this)[i]; 75 | } 76 | ss << "]"; 77 | } 78 | return ss.str(); 79 | } 80 | 81 | void TransactionSequence::dump() const { 82 | cout << to_string(); 83 | } 84 | 85 | ostream& operator<<(std::ostream& out, const TransactionSequence& sequence){ 86 | out << sequence.to_string(); 87 | return out; 88 | } 89 | 90 | 91 | } // namespace 92 | -------------------------------------------------------------------------------- /src/transaction/undo_buffer.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/transaction/undo_buffer.hpp" 19 | 20 | #include 21 | #include 22 | 23 | using namespace std; 24 | 25 | namespace teseo::transaction { 26 | 27 | UndoBuffer* UndoBuffer::allocate(uint32_t buffer_sz){ 28 | void* ptr = malloc(undobuffer_sz(buffer_sz)); 29 | if(ptr == nullptr) throw bad_alloc(); 30 | return new (ptr) UndoBuffer(buffer_sz); 31 | } 32 | 33 | void UndoBuffer::deallocate(UndoBuffer* undobuffer){ 34 | if(undobuffer != nullptr){ 35 | undobuffer->~UndoBuffer(); 36 | ::free(undobuffer); 37 | } 38 | } 39 | 40 | 41 | } // namespace 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/util/chrono.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/util/chrono.hpp" 19 | 20 | #include 21 | 22 | using namespace std; 23 | using namespace std::chrono; 24 | 25 | namespace teseo::util { 26 | 27 | string to_string(const time_point& tp){ 28 | auto secs = duration_cast(tp.time_since_epoch()).count(); 29 | auto str = string( ctime(&secs) ); 30 | return str.substr(0, str.size() -1); // remove the trailing \n 31 | } 32 | 33 | } // namespace 34 | -------------------------------------------------------------------------------- /src/util/error.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/util/error.hpp" 19 | 20 | using namespace std; 21 | 22 | namespace teseo { 23 | 24 | Exception::Exception(const std::string& exc_class, const std::string& message, const std::string& file, int line, const std::string& function) 25 | : runtime_error(message), m_class(exc_class), m_file(file), m_line(line), m_function(function){ } 26 | 27 | const std::string& Exception::file() const{ return m_file; } 28 | int Exception::line() const{ return m_line; } 29 | const std::string& Exception::function() const{ return m_function; } 30 | const std::string& Exception::exception_class() const { return m_class; } 31 | 32 | std::ostream& operator<<(std::ostream& out, Exception& e){ 33 | out << "[" << e.exception_class() << ": " << e.what() << " - Raised at: `" << e.file() << "', " 34 | "line: " << e.line() << ", function: `" << e.function() << "']"; 35 | return out; 36 | } 37 | 38 | LogicalError::LogicalError(const std::string& exc_class, const std::string& message, const std::string& file, int line, const std::string& function) : 39 | Exception(exc_class, message, file, line, function){ } 40 | 41 | TransactionConflict::TransactionConflict(const std::string& exc_class, const std::string& message, const std::string& file, int line, const std::string& function) : 42 | Exception(exc_class, message, file, line, function){ } 43 | 44 | VertexError::VertexError(uint64_t vertex, const std::string& exc_class, const std::string& message, const std::string& file, int line, const std::string& function) : 45 | LogicalError(exc_class, message, file, line, function), m_vertex(vertex) { } 46 | 47 | uint64_t VertexError::vertex() const noexcept { return m_vertex; } 48 | 49 | EdgeError::EdgeError(uint64_t source, uint64_t destination, const std::string& exc_class, const std::string& message, const std::string& file, int line, const std::string& function): 50 | LogicalError(exc_class, message, file, line, function), m_source(source), m_destination(destination) { } 51 | 52 | uint64_t EdgeError::source() const noexcept { return m_source; } 53 | 54 | uint64_t EdgeError::destination() const noexcept { return m_destination; } 55 | 56 | } // namespace 57 | 58 | namespace teseo::util { 59 | 60 | // globals 61 | stringstream g_exception_stream; 62 | mutex g_exception_mutex; 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/util/interface.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/util/interface.hpp" 19 | 20 | #include "teseo/memstore/error.hpp" 21 | #include "teseo/memstore/key.hpp" 22 | #include "teseo/util/error.hpp" 23 | 24 | using namespace std; 25 | 26 | namespace teseo::util { 27 | 28 | void handle_error(const memstore::Error& error){ 29 | using namespace memstore; 30 | 31 | const uint64_t source = error.m_key.source() -1; // external vertex 0 -> internal vertex 1 32 | const uint64_t destination = error.m_key.destination() -1; // external vertex 0 -> internal vertex 1 33 | 34 | switch(error.m_type){ 35 | case Error::VertexLocked: 36 | RAISE(TransactionConflict, "Conflict detected, the vertex " << source << " is currently locked by another transaction. " 37 | "Restart this transaction to alter this object"); 38 | case Error::VertexAlreadyExists: 39 | VERTEX_ERROR(source, "The vertex " << source << " already exists"); 40 | case Error::VertexDoesNotExist: 41 | VERTEX_ERROR(source, "The vertex " << source << " does not exist"); 42 | case Error::VertexPhantomWrite: 43 | RAISE(TransactionConflict, "Conflict detected, phantom write detected for the vertex " << source); 44 | case Error::VertexInvalidLogicalID: 45 | VERTEX_ERROR(source, "Invalid logical vertex identifier: " << source); 46 | case Error::EdgeLocked: 47 | RAISE(TransactionConflict, "Conflict detected, the edge " << source << " -> " << destination << " is currently locked " 48 | "by another transaction. Restart this transaction to alter this object"); 49 | case Error::EdgeAlreadyExists: 50 | EDGE_ERROR(source, destination, "The edge " << source << " -> " << destination << " already exists"); 51 | case Error::EdgeDoesNotExist: 52 | EDGE_ERROR(source, destination, "The edge " << source << " -> " << destination << " does not exist"); 53 | case Error::EdgeSelf: 54 | EDGE_ERROR(source, destination, "Edges having the same source and destination are not supported: " << source << " -> " << destination); 55 | case Error::TooManyReaders: 56 | RAISE(LogicalError, "There are too many readers accessing the same segment. Re-try again later..."); 57 | default: 58 | RAISE(InternalError, "Error type not registered"); 59 | } 60 | } 61 | 62 | } // namespace 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/util/libevent.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #include "teseo/util/libevent.hpp" 18 | 19 | #include 20 | #include // libevent_global_shutdown 21 | #include // evthread_use_pthreads 22 | #include 23 | #include 24 | 25 | #include "teseo/util/error.hpp" 26 | 27 | //#define DEBUG 28 | //#include "teseo/util/debug.hpp" 29 | 30 | using namespace std; 31 | 32 | namespace teseo::util { 33 | 34 | static int g_libevent_active_clients = 0; // number of invocations libevent_init - invocations to libevent_shutdown 35 | static mutex g_libevent_mutex; // concurrency protection for multiple invocations to libevent_init and libevent_shutdown 36 | 37 | void LibEvent::init(){ 38 | scoped_lock lock(g_libevent_mutex); 39 | assert(g_libevent_active_clients >= 0 && "Negative counter"); 40 | if(g_libevent_active_clients > 0){ 41 | g_libevent_active_clients += 1; 42 | } else { 43 | int rc = evthread_use_pthreads(); 44 | if(rc != 0) RAISE_EXCEPTION(InternalError, "[libevent_init] Cannot initialise the library"); 45 | assert(g_libevent_active_clients == 0 && "Multiple inits of the same library?"); 46 | g_libevent_active_clients = 1; 47 | } 48 | } 49 | 50 | void LibEvent::shutdown(){ 51 | scoped_lock lock(g_libevent_mutex); 52 | assert(g_libevent_active_clients >= 0 && "Negative counter"); 53 | if(g_libevent_active_clients == 1){ 54 | libevent_global_shutdown(); // it doesn't return anything 55 | } 56 | g_libevent_active_clients -= 1; 57 | } 58 | 59 | static int collect_events(const struct event_base*, const struct event* event, void* /* vector* */ argument){ 60 | // event_get_events: bad naming, it retrieves the flags associated to an event. 61 | // The guard should protect against static & expired events 62 | if(event_get_events(event) & EV_TIMEOUT){ 63 | auto vector_elements = reinterpret_cast*>(argument); 64 | vector_elements->push_back(const_cast(event)); 65 | } 66 | return 0; // 0 => keep iterating 67 | } 68 | 69 | vector LibEvent::get_pending_events(struct event_base* queue) { 70 | vector pending_events; 71 | int rc = event_base_foreach_event(queue, collect_events, &pending_events); // thread safe 72 | if(rc != 0) ERROR("event_base_foreach_event"); 73 | return pending_events; 74 | } 75 | 76 | 77 | } // namespace 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/util/system.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #include "teseo/util/system.hpp" 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "teseo/util/error.hpp" 24 | 25 | using namespace std; 26 | 27 | namespace teseo::util { 28 | 29 | string System::hostname(){ 30 | constexpr int len = 512; 31 | char buffer[len]; 32 | auto rc = gethostname(buffer, len); 33 | if(rc != 0){ 34 | RAISE(InternalError, "[hostname] Cannot retrieve the hostname: " << strerror(errno) << " (" << errno << ")"); 35 | } 36 | string hostname{buffer}; 37 | 38 | // Remove the suffix `.scilens.private' from the machines in the Scilens cluster 39 | const string scilens_suffix = ".scilens.private"; 40 | if(hostname.length() >= scilens_suffix.length()){ 41 | auto scilens_match = hostname.rfind(scilens_suffix); 42 | if(scilens_match != string::npos && scilens_match == hostname.length() - scilens_suffix.length()){ 43 | hostname.replace(scilens_match, scilens_suffix.length(), nullptr, 0); 44 | } 45 | } 46 | 47 | return hostname; 48 | } 49 | 50 | 51 | } // namespace 52 | -------------------------------------------------------------------------------- /src/util/thread.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "teseo/util/thread.hpp" 19 | 20 | #include 21 | #include 22 | #include 23 | #if __has_include() 24 | #include 25 | #endif 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "teseo/util/error.hpp" 32 | 33 | using namespace std; 34 | 35 | namespace teseo::util { 36 | 37 | int64_t Thread::get_thread_id(){ 38 | auto tid = (int64_t) syscall(SYS_gettid); 39 | assert(tid > 0); 40 | return tid; 41 | } 42 | 43 | int Thread::get_cpu_id(){ 44 | int cpu_id = sched_getcpu(); 45 | if(cpu_id < 0){ RAISE_EXCEPTION(InternalError, "[Thread::get_cpu_id] sched_getcpu error: " << strerror(errno) << " (" << errno << ")"); } 46 | return cpu_id; 47 | } 48 | 49 | int Thread::get_numa_id(){ 50 | #if __has_include() 51 | int cpu_id = get_cpu_id(); 52 | int node_id = numa_node_of_cpu(cpu_id); 53 | if(node_id < 0){ RAISE_EXCEPTION(InternalError, "[Thread::get_numa_id] numa_node_of_cpu error: " << strerror(errno) << " (" << errno << ")"); } 54 | return node_id; 55 | #else 56 | return 0; 57 | #endif 58 | } 59 | 60 | int64_t Thread::get_process_id(){ 61 | return getpid(); // unistd.h 62 | } 63 | 64 | string Thread::get_name(){ 65 | pthread_t thread_id = pthread_self(); 66 | constexpr size_t buffer_sz = 64; 67 | char buffer[buffer_sz]; 68 | int rc = pthread_getname_np(thread_id, buffer, buffer_sz); 69 | if(rc != 0){ 70 | RAISE_EXCEPTION(InternalError, "[Thread::get_name] error: " << strerror(errno) << " (" << errno << ")"); 71 | } 72 | return string(buffer); 73 | } 74 | 75 | void Thread::set_name(const string& name){ 76 | pthread_t thread_id = pthread_self(); 77 | string truncated_name = name.substr(0, 15); 78 | int rc = pthread_setname_np(thread_id, truncated_name.c_str()); 79 | if(rc != 0){ 80 | RAISE_EXCEPTION(InternalError, "[Thread::set_name] error: " << strerror(errno) << " (" << errno << ")"); 81 | } 82 | } 83 | 84 | 85 | } // namespace 86 | -------------------------------------------------------------------------------- /tests/catch.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | // define main() for the test suite 19 | #define CATCH_CONFIG_MAIN 20 | 21 | #include "catch.hpp" 22 | -------------------------------------------------------------------------------- /tests/test_circular_array.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | 19 | #include "catch.hpp" 20 | 21 | #include 22 | #include 23 | 24 | #include "teseo/util/timer.hpp" 25 | #include "teseo/util/circular_array.hpp" 26 | 27 | using namespace std; 28 | using namespace teseo::util; 29 | 30 | TEST_CASE("ca_resize1", "[circular_array]") { 31 | CircularArray queue {4}; 32 | 33 | REQUIRE(queue.size() == 0); 34 | REQUIRE(queue.empty() == true); 35 | 36 | queue.append(0); 37 | REQUIRE(queue.size() == 1); 38 | REQUIRE(queue.empty() == false); 39 | 40 | queue.append(1); 41 | queue.append(2); 42 | queue.append(3); 43 | 44 | REQUIRE(queue.size() == 4); 45 | REQUIRE(queue.empty() == false); 46 | REQUIRE(queue[0] == 0); 47 | REQUIRE(queue[1] == 1); 48 | REQUIRE(queue[2] == 2); 49 | REQUIRE(queue[3] == 3); 50 | 51 | queue.append(4); 52 | REQUIRE(queue.capacity() == 8); 53 | REQUIRE(queue.size() == 5); 54 | REQUIRE(queue.empty() == false); 55 | REQUIRE(queue[0] == 0); 56 | REQUIRE(queue[1] == 1); 57 | REQUIRE(queue[2] == 2); 58 | REQUIRE(queue[3] == 3); 59 | REQUIRE(queue[4] == 4); 60 | } 61 | -------------------------------------------------------------------------------- /tests/test_merger.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include "catch.hpp" 19 | 20 | #include 21 | #include 22 | 23 | #include "teseo/context/global_context.hpp" 24 | #include "teseo/context/scoped_epoch.hpp" 25 | #include "teseo/memstore/context.hpp" 26 | #include "teseo/memstore/index.hpp" 27 | #include "teseo/memstore/leaf.hpp" 28 | #include "teseo/memstore/memstore.hpp" 29 | #include "teseo/memstore/segment.hpp" 30 | #include "teseo/rebalance/merger_service.hpp" 31 | #include "teseo.hpp" 32 | 33 | using namespace std; 34 | using namespace teseo; 35 | using namespace teseo::context; 36 | using namespace teseo::memstore; 37 | using namespace teseo::rebalance; 38 | 39 | 40 | TEST_CASE("merger_start_and_stop", "[merger]"){ 41 | Teseo teseo; 42 | Memstore* memstore = global_context()->memstore(); 43 | 44 | memstore->merger()->stop(); 45 | memstore->merger()->start(); 46 | memstore->merger()->stop(); 47 | memstore->merger()->start(); 48 | memstore->merger()->stop(); 49 | } 50 | 51 | TEST_CASE("merger_prune", "[merger]"){ // check vertices have been pruned 52 | Teseo teseo; 53 | Memstore* memstore = global_context()->memstore(); 54 | 55 | { 56 | auto tx = teseo.start_transaction(); 57 | tx.insert_vertex(10); 58 | tx.commit(); 59 | } 60 | 61 | { 62 | auto tx = teseo.start_transaction(); 63 | tx.remove_vertex(10); 64 | tx.commit(); 65 | } 66 | 67 | memstore->merger()->execute_now(); 68 | 69 | ScopedEpoch epoch; // to perform an index traversal 70 | Segment* segment = memstore->index()->find(0).leaf()->get_segment(0); 71 | REQUIRE(segment->used_space() == 0); 72 | } 73 | 74 | TEST_CASE("merger_merge", "[merger]"){ 75 | Teseo teseo; 76 | Memstore* memstore = global_context()->memstore(); 77 | MergerService* merger = memstore->merger(); 78 | 79 | constexpr uint64_t vertex_max = 1000; 80 | 81 | for(uint64_t vertex_id = 10; vertex_id <= vertex_max; vertex_id += 10){ 82 | auto tx = teseo.start_transaction(); 83 | tx.insert_vertex(vertex_id); 84 | tx.commit(); 85 | this_thread::sleep_for(10ms); // give time to the rebalancers to pick up 86 | } 87 | 88 | // remove half of the vertices 89 | uint64_t base_vertices[] = {20, 40, 50, 60, 80}; 90 | for(auto base : base_vertices){ 91 | for(uint64_t vertex_id = base; vertex_id <= vertex_max; vertex_id += 100){ 92 | auto tx = teseo.start_transaction(); 93 | tx.remove_vertex(vertex_id); 94 | tx.commit(); 95 | this_thread::sleep_for(10ms); // give time to the rebalancers to pick up 96 | } 97 | } 98 | 99 | merger->execute_now(); 100 | } 101 | 102 | 103 | -------------------------------------------------------------------------------- /tests/test_transaction_impl.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2019 Dean De Leo, email: dleo[at]cwi.nl 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #include "catch.hpp" 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "teseo/context/global_context.hpp" 26 | #include "teseo/context/static_configuration.hpp" 27 | #include "teseo/context/thread_context.hpp" 28 | #include "teseo/transaction/transaction_impl.hpp" 29 | #include "teseo.hpp" 30 | 31 | using namespace std; 32 | using namespace teseo; 33 | using namespace teseo::context; 34 | using namespace teseo::transaction; 35 | 36 | TEST_CASE("txn_create_direct", "[transaction]" ){ 37 | GlobalContext instance; 38 | TransactionImpl* tx_impl = thread_context()->create_transaction(); 39 | // 3/May/2020: the user count is already 1 at creation 40 | //tx_impl->incr_user_count(); 41 | 42 | 43 | tx_impl->decr_user_count(); 44 | tx_impl = nullptr; // do not invoke delete 45 | } 46 | 47 | 48 | TEST_CASE("txn_create_interface", "[transaction]" ){ 49 | Teseo instance; 50 | auto txn = instance.start_transaction(); 51 | } 52 | 53 | --------------------------------------------------------------------------------