├── test ├── tmp │ └── .gitignore ├── data │ ├── sharded_filter8_tiny.bin │ └── sample.txt ├── helpers.hpp ├── CMakeLists.txt ├── filter.cpp └── sharded_filter.cpp ├── .gitmodules ├── scripts ├── clang-format.sh └── clang-tidy.sh ├── .gitignore ├── .github └── workflows │ ├── freebsd.yml │ ├── ubuntu.yml │ └── msys2.yml ├── .clang-tidy ├── CMakeLists.txt ├── .clang-format ├── bench └── large.cpp ├── include └── binfuse │ ├── filter.hpp │ └── sharded_filter.hpp ├── LICENSE └── README.md /test/tmp/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /test/data/sharded_filter8_tiny.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oschonrock/binfuse/HEAD/test/data/sharded_filter8_tiny.bin -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "ext/xor_singleheader"] 2 | path = ext/xor_singleheader 3 | url = https://github.com/FastFilter/xor_singleheader.git 4 | [submodule "ext/mio"] 5 | path = ext/mio 6 | url = https://github.com/oschonrock/mio.git 7 | -------------------------------------------------------------------------------- /scripts/clang-format.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # in adition to your IDE clang-format,it is worth running this 4 | # periodically to ensure all formatting errors have been caught. 5 | 6 | find test/ include/ bench/ -type f -name '*.cpp' -or -name '*.hpp' | xargs clang-format --verbose -i 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | build 34 | .cache 35 | compile_commands.json 36 | -------------------------------------------------------------------------------- /.github/workflows/freebsd.yml: -------------------------------------------------------------------------------- 1 | name: FreeBSD-14.1 clang-18.1 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | freebsd-build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: checkout repo 10 | uses: actions/checkout@v4 11 | with: 12 | submodules: 'recursive' 13 | 14 | - name: build with cmake in FreeBSD vm 15 | uses: vmactions/freebsd-vm@v1.1.5 16 | with: 17 | usesh: true 18 | prepare: | 19 | pkg install -y cmake 20 | 21 | run: | 22 | cmake -S . -B build -DCMAKE_BUILD_TYPE=debug && # debug includes sanitizers 23 | cmake --build build # includes tests by default, tests are run with env set to fail on sanitizers 24 | -------------------------------------------------------------------------------- /scripts/clang-tidy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # in adition to your IDE clang-tidy,it is worth running this 4 | # periodically to ensure all warnings have been caught. This is 5 | # particularly true with respect to #include warnings which have been 6 | # masked by precompiled headers 7 | 8 | # ensure we have genrated a compile_commands.json without precompiled headers 9 | cmake -S . -B build >/dev/null 10 | 11 | # Use clang-tidy -p to force read of compile_commands.json in the 12 | # current directory. This is quite a slow process and may take 13 | # several minutes, hence the use of gnu parallel. 14 | time find include/ test/ -type f -name '*.cpp' -or -name '*.hpp' | \ 15 | nice parallel -q clang-tidy --quiet -p --config-file=.clang-tidy \ 16 | -header-filter='.*/binfuse/include/.*' --use-color 17 | -------------------------------------------------------------------------------- /.github/workflows/ubuntu.yml: -------------------------------------------------------------------------------- 1 | name: Ubuntu 24.04 (gcc-13, clang-18) 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | ubuntu-build: 7 | runs-on: ubuntu-24.04 8 | strategy: 9 | matrix: 10 | compiler: [gcc, clang] 11 | steps: 12 | - name: checkout code 13 | uses: actions/checkout@v4 14 | with: 15 | submodules: 'recursive' 16 | - name: build with cmake 17 | run: | 18 | if [ "${{ matrix.compiler }}" == "gcc" ]; then 19 | export CC=gcc 20 | export CXX=g++ 21 | elif [ "${{ matrix.compiler }}" == "clang" ]; then 22 | export CC=clang 23 | export CXX=clang++ 24 | fi 25 | cmake -S . -B build -DCMAKE_BUILD_TYPE=debug && # debug includes sanitizers 26 | cmake --build build # includes tests by default, tests are run with env set to fail on sanitizers 27 | -------------------------------------------------------------------------------- /.github/workflows/msys2.yml: -------------------------------------------------------------------------------- 1 | name: Windows MINGW32/64 gcc/clang 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | windows-mingw: 7 | name: ${{ matrix.sys }} 8 | runs-on: windows-latest 9 | defaults: 10 | run: 11 | shell: msys2 {0} 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | sys: [ UCRT64, CLANG64, MINGW64, MINGW32 ] 16 | steps: 17 | - name: checkout code 18 | uses: actions/checkout@v4 19 | with: 20 | submodules: 'recursive' 21 | 22 | - name: install msys2 23 | uses: msys2/setup-msys2@v2 24 | with: 25 | msystem: ${{matrix.sys}} 26 | update: true 27 | pacboy: >- 28 | toolchain 29 | cmake 30 | ninja 31 | 32 | - name: Configure 33 | run: cmake -G Ninja -S . -B build -DCMAKE_BUILD_TYPE=debug 34 | 35 | - name: Build 36 | run: cmake --build build 37 | -------------------------------------------------------------------------------- /test/helpers.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | inline std::vector load_sample() { 12 | std::ifstream sample("data/sample.txt"); 13 | std::vector keys; 14 | for (std::string line; std::getline(sample, line);) { 15 | std::uint64_t key{}; 16 | std::from_chars(line.data(), line.data() + line.size(), key, 16); 17 | keys.emplace_back(key); 18 | } 19 | return keys; 20 | } 21 | 22 | template 23 | [[nodiscard]] static double estimate_false_positive_rate(const F& fil) { 24 | auto gen = std::mt19937_64(std::random_device{}()); 25 | std::size_t matches = 0; 26 | const size_t sample_size = 1'000'000; 27 | for (size_t t = 0; t < sample_size; t++) { 28 | if (fil.contains(gen())) { // no distribution needed 29 | matches++; 30 | } 31 | } 32 | return static_cast(matches) / static_cast(sample_size); 33 | } 34 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | Checks: '*, 2 | -fuchsia*, 3 | -llvmlibc*, 4 | -*braces-around-statements, 5 | -hicpp-noexcept-move, 6 | -readability-named-parameter, 7 | -modernize-use-trailing-return-type, 8 | -bugprone-narrowing-conversions, 9 | -google-runtime-references, 10 | -cppcoreguidelines-pro-bounds-constant-array-index, 11 | -misc-non-private-member-variables-in-classes, 12 | -cppcoreguidelines-avoid-magic-numbers, 13 | -readability-magic-numbers, 14 | -altera-struct-pack-align, 15 | -cppcoreguidelines-non-private-member-variables-in-classes, 16 | -abseil-string-find-str-contains, 17 | -google-runtime-int, 18 | -cppcoreguidelines-pro-bounds-pointer-arithmetic, 19 | -cppcoreguidelines-pro-bounds-array-to-pointer-decay, 20 | -cppcoreguidelines-pro-type-union-access, 21 | -altera-unroll-loops, 22 | -altera-id-dependent-backward-branch, 23 | -bugprone-easily-swappable-parameters, 24 | -google-readability-todo, 25 | -llvm-header-guard, 26 | -readability-identifier-length 27 | -cppcoreguidelines-avoid-c-arrays, 28 | -modernize-avoid-c-arrays, 29 | -hicpp-avoid-c-arrays, 30 | -readability-identifier-length, 31 | -cppcoreguidelines-avoid-non-const-global-variables, 32 | -cert-err58-cpp, 33 | -google-readability-casting, 34 | -cppcoreguidelines-pro-type-cstyle-cast, 35 | -readability-implicit-bool-conversion, 36 | -modernize-use-using, 37 | -cppcoreguidelines-owning-memory, 38 | -cppcoreguidelines-no-malloc, 39 | -readability-function-cognitive-complexity, 40 | -readability-isolate-declaration, 41 | -hicpp-no-malloc, 42 | -modernize-use-auto, 43 | -misc-const-correctness' 44 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24") 3 | cmake_policy(SET CMP0135 NEW) 4 | endif() 5 | 6 | include(FetchContent) 7 | FetchContent_Declare( 8 | googletest 9 | URL https://github.com/google/googletest/archive/refs/tags/v1.15.2.zip 10 | ) 11 | # For Windows: Prevent overriding the parent project's compiler/linker settings 12 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 13 | set(INSTALL_GTEST OFF CACHE BOOL "Disable installing GTEST") 14 | FetchContent_MakeAvailable(googletest) 15 | 16 | include(GoogleTest) 17 | 18 | include_directories(${CMAKE_SOURCE_DIR}/include) 19 | 20 | function (add_unit_test UNIT_TEST) 21 | set(UNIT_TESTS ${UNIT_TESTS} ${UNIT_TEST} PARENT_SCOPE) 22 | add_executable(${UNIT_TEST} ${UNIT_TEST}.cpp) 23 | target_compile_options(${UNIT_TEST} PRIVATE ${PROJECT_COMPILE_OPTIONS}) 24 | target_compile_features(${UNIT_TEST} PRIVATE cxx_std_20) 25 | target_link_libraries(${UNIT_TEST} PRIVATE gtest_main ${ARGN}) 26 | gtest_discover_tests(${UNIT_TEST} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) 27 | endfunction() 28 | 29 | add_unit_test(filter binfuse xor_singleheader mio) 30 | add_unit_test(sharded_filter binfuse xor_singleheader mio) 31 | 32 | add_custom_target(binfuse_all_tests ALL DEPENDS ${all_targets} ${UNIT_TESTS}) 33 | 34 | add_custom_command( 35 | TARGET binfuse_all_tests 36 | POST_BUILD 37 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 38 | COMMAND env 39 | ASAN_OPTIONS='halt_on_error=1:abort_on_error=1:print_summary=1' 40 | UBSAN_OPTIONS='halt_on_error=1:abort_on_error=1:print_summary=1:print_stacktrace=1' 41 | ${CMAKE_CTEST_COMMAND} 42 | -C $ --output-on-failure # --verbose 43 | USES_TERMINAL 44 | ) 45 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | project(binfuse) 3 | 4 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 5 | 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | set(CMAKE_CXX_EXTENSIONS OFF) 8 | set(CMAKE_CXX_SCAN_FOR_MODULES OFF) 9 | 10 | if (MSVC) 11 | list(APPEND PROJECT_COMPILE_OPTIONS /W3) 12 | string(APPEND CMAKE_CXX_FLAGS_DEBUG " /fsanitize=address") 13 | else() # *nix 14 | list(APPEND PROJECT_COMPILE_OPTIONS -Wall -Wextra -Wpedantic -Wshadow -Wextra-semi 15 | -Wmissing-noreturn -Wconversion -Wsign-conversion -Wno-ignored-attributes -Werror) 16 | 17 | if (MINGW) 18 | if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 19 | # sanitizers are not working under mingw, except in CLANG64, 20 | # with clang as compiler, but then it doesn't support leak 21 | string(APPEND CMAKE_CXX_FLAGS_DEBUG " -fsanitize=address,undefined") 22 | endif() 23 | else() 24 | # other *nix compilers support a wider set of sanitizers 25 | string(APPEND CMAKE_CXX_FLAGS_DEBUG " -fsanitize=address,undefined,leak") 26 | endif() 27 | endif() 28 | 29 | add_subdirectory(ext/xor_singleheader) 30 | 31 | add_subdirectory(ext/mio) 32 | 33 | add_library(binfuse INTERFACE) 34 | target_include_directories(binfuse INTERFACE include) 35 | target_compile_features(binfuse INTERFACE cxx_std_20) 36 | target_link_libraries(binfuse INTERFACE xor_singleheader mio) 37 | 38 | option(BINFUSE_BENCH "Build BINFUSE benchmark" OFF) 39 | if(BINFUSE_BENCH) 40 | add_executable(binfuse_bench_large bench/large.cpp) 41 | target_compile_options(binfuse_bench_large PRIVATE ${PROJECT_COMPILE_OPTIONS}) 42 | target_compile_features(binfuse_bench_large PRIVATE cxx_std_20) 43 | target_link_libraries(binfuse_bench_large PRIVATE binfuse) 44 | endif() 45 | 46 | # testing 47 | 48 | option(BINFUSE_TEST "Enable BINFUSE tests" ON) 49 | if(BINFUSE_TEST) 50 | get_property(all_targets DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY BUILDSYSTEM_TARGETS) 51 | enable_testing() 52 | add_subdirectory(test) 53 | else(BINFUSE_TEST) 54 | message(STATUS "BINFUSE Tests are disabled. Set BINFUSE_TEST to ON to run tests.") 55 | endif(BINFUSE_TEST) 56 | 57 | # make compile commands available for IDEs etc 58 | execute_process( 59 | COMMAND ${CMAKE_COMMAND} -E copy 60 | ${CMAKE_BINARY_DIR}/compile_commands.json 61 | ${CMAKE_SOURCE_DIR}/compile_commands.json 62 | ) 63 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | AccessModifierOffset: -2 4 | AlignAfterOpenBracket: Align 5 | AlignConsecutiveMacros: false 6 | AlignConsecutiveAssignments: true 7 | AlignConsecutiveDeclarations: true 8 | AlignEscapedNewlines: Right 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllArgumentsOnNextLine: true 12 | AllowAllConstructorInitializersOnNextLine: true 13 | AllowAllParametersOfDeclarationOnNextLine: true 14 | AllowShortBlocksOnASingleLine: false 15 | AllowShortCaseLabelsOnASingleLine: false 16 | AllowShortFunctionsOnASingleLine: All 17 | AllowShortLambdasOnASingleLine: All 18 | AllowShortIfStatementsOnASingleLine: WithoutElse 19 | AllowShortLoopsOnASingleLine: true 20 | AlwaysBreakAfterDefinitionReturnType: None 21 | AlwaysBreakAfterReturnType: None 22 | AlwaysBreakBeforeMultilineStrings: false 23 | AlwaysBreakTemplateDeclarations: Yes 24 | BinPackArguments: true 25 | BinPackParameters: true 26 | BraceWrapping: 27 | AfterCaseLabel: false 28 | AfterClass: false 29 | AfterControlStatement: false 30 | AfterEnum: false 31 | AfterFunction: false 32 | AfterNamespace: false 33 | AfterObjCDeclaration: false 34 | AfterStruct: false 35 | AfterUnion: false 36 | AfterExternBlock: false 37 | BeforeCatch: false 38 | BeforeElse: false 39 | IndentBraces: false 40 | SplitEmptyFunction: true 41 | SplitEmptyRecord: true 42 | SplitEmptyNamespace: true 43 | BreakBeforeBinaryOperators: None 44 | BreakBeforeBraces: Attach 45 | BreakBeforeInheritanceComma: false 46 | BreakInheritanceList: BeforeColon 47 | BreakBeforeTernaryOperators: true 48 | BreakConstructorInitializersBeforeComma: false 49 | BreakConstructorInitializers: BeforeColon 50 | BreakAfterJavaFieldAnnotations: false 51 | BreakStringLiterals: true 52 | ColumnLimit: 100 53 | CommentPragmas: '^ IWYU pragma:' 54 | CompactNamespaces: false 55 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 56 | ConstructorInitializerIndentWidth: 4 57 | ContinuationIndentWidth: 4 58 | Cpp11BracedListStyle: true 59 | DerivePointerAlignment: false 60 | DisableFormat: false 61 | ExperimentalAutoDetectBinPacking: false 62 | FixNamespaceComments: true 63 | ForEachMacros: 64 | - foreach 65 | - Q_FOREACH 66 | - BOOST_FOREACH 67 | IncludeBlocks: Preserve 68 | IncludeCategories: 69 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 70 | Priority: 2 71 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 72 | Priority: 3 73 | - Regex: '.*' 74 | Priority: 1 75 | IncludeIsMainRegex: '(Test)?$' 76 | IndentCaseLabels: false 77 | IndentPPDirectives: None 78 | IndentWidth: 2 79 | IndentWrappedFunctionNames: false 80 | JavaScriptQuotes: Leave 81 | JavaScriptWrapImports: true 82 | KeepEmptyLinesAtTheStartOfBlocks: true 83 | MacroBlockBegin: '' 84 | MacroBlockEnd: '' 85 | MaxEmptyLinesToKeep: 1 86 | NamespaceIndentation: None 87 | ObjCBinPackProtocolList: Auto 88 | ObjCBlockIndentWidth: 2 89 | ObjCSpaceAfterProperty: false 90 | ObjCSpaceBeforeProtocolList: true 91 | PenaltyBreakAssignment: 2 92 | PenaltyBreakBeforeFirstCallParameter: 19 93 | PenaltyBreakComment: 300 94 | PenaltyBreakFirstLessLess: 120 95 | PenaltyBreakString: 1000 96 | PenaltyBreakTemplateDeclaration: 10 97 | PenaltyExcessCharacter: 1000000 98 | PenaltyReturnTypeOnItsOwnLine: 60 99 | PointerAlignment: Left 100 | ReflowComments: true 101 | SortIncludes: true 102 | SortUsingDeclarations: true 103 | SpaceAfterCStyleCast: false 104 | SpaceAfterLogicalNot: false 105 | SpaceAfterTemplateKeyword: true 106 | SpaceBeforeAssignmentOperators: true 107 | SpaceBeforeCpp11BracedList: false 108 | SpaceBeforeCtorInitializerColon: true 109 | SpaceBeforeInheritanceColon: true 110 | SpaceBeforeParens: ControlStatements 111 | SpaceBeforeRangeBasedForLoopColon: false 112 | SpaceInEmptyParentheses: false 113 | SpacesBeforeTrailingComments: 1 114 | SpacesInAngles: false 115 | SpacesInContainerLiterals: true 116 | SpacesInCStyleCastParentheses: false 117 | SpacesInParentheses: false 118 | SpacesInSquareBrackets: false 119 | Standard: Cpp11 120 | StatementMacros: 121 | - Q_UNUSED 122 | - QT_REQUIRE_VERSION 123 | TabWidth: 8 124 | UseTab: Never 125 | ... 126 | -------------------------------------------------------------------------------- /bench/large.cpp: -------------------------------------------------------------------------------- 1 | #include "binfuse/sharded_filter.hpp" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using clk = std::chrono::high_resolution_clock; 14 | 15 | std::vector gen_shard(std::uint64_t prefix, std::uint8_t shard_bits, 16 | std::size_t size) { 17 | 18 | std::mt19937_64 gen{std::random_device{}()}; 19 | 20 | std::uint8_t shift = 64 - shard_bits; 21 | const auto min = prefix << shift; 22 | const auto max = ((prefix + 1) << shift) - 1UL; 23 | 24 | std::uniform_int_distribution dist(min, max); 25 | 26 | std::vector shard; 27 | shard.reserve(size); 28 | for (std::size_t i = 0; i != size; ++i) { 29 | shard.push_back(dist(gen)); 30 | } 31 | return shard; 32 | } 33 | 34 | double ratio(std::integral auto numerator, std::integral auto denominator) { 35 | return static_cast(numerator) / static_cast(denominator); 36 | } 37 | 38 | double dratio(auto duration, std::integral auto denominator) { 39 | using nanos = std::chrono::duration; 40 | return duration_cast(duration).count() / static_cast(denominator); 41 | } 42 | 43 | template 44 | void populate(T& filter, std::uint32_t shards, std::uint8_t shard_bits, std::size_t shard_size) { 45 | clk::duration gen_shard_total{}; 46 | clk::duration popluate_filter_total{}; 47 | clk::duration verify_filter_total{}; 48 | clk::duration add_shard_total{}; 49 | for (std::uint32_t prefix = 0; prefix != shards; ++prefix) { 50 | std::cerr << std::format("populate: {:6.1f}%\x1B[17D", 100 * ratio(prefix, shards)); 51 | auto start = clk::now(); 52 | const auto shard_keys = gen_shard(prefix, shard_bits, shard_size); 53 | gen_shard_total += clk::now() - start; 54 | 55 | start = clk::now(); 56 | typename T::shard_filter_t shard(shard_keys); 57 | popluate_filter_total += clk::now() - start; 58 | 59 | start = clk::now(); 60 | if (!shard.verify(shard_keys)) { 61 | throw std::runtime_error("verify failed!!"); 62 | } 63 | verify_filter_total += clk::now() - start; 64 | 65 | start = clk::now(); 66 | filter.add_shard(shard, prefix); 67 | add_shard_total += clk::now() - start; 68 | } 69 | auto size = shards * shard_size; 70 | std::cout << std::format("f{:<2d} {:8.1f}ns {:8.1f}ns {:8.1f}ns {:8.1f}ns", T::nbits, 71 | dratio(gen_shard_total, size), dratio(popluate_filter_total, size), 72 | dratio(verify_filter_total, size), dratio(add_shard_total, size)); 73 | } 74 | 75 | template 76 | void query(const T& filter, std::size_t size) { 77 | std::mt19937_64 gen{std::random_device{}()}; 78 | 79 | auto iterations = std::min(size, 1'000'000UL); 80 | 81 | // gen first to avoid measuring the random number generation 82 | std::vector random_keys; 83 | random_keys.reserve(iterations); 84 | for (std::size_t i = 0; i != iterations; ++i) { 85 | random_keys.emplace_back(gen()); 86 | } 87 | 88 | // this is slower than verify, because each query is random and 89 | // likely with a different prefix, so the pointer hop is an almost 90 | // guaranteed far cache miss, even if mmap is fully loaded. 91 | auto start = clk::now(); 92 | std::size_t found_count = 0; 93 | for (auto key: random_keys) { 94 | found_count += filter.contains(key); 95 | } 96 | auto end = clk::now(); 97 | std::cout << std::format(" {:8.1f}ns {:.6f}%\n", dratio(end - start, iterations), 98 | 100 * ratio(found_count, iterations)); 99 | } 100 | 101 | int main() { 102 | 103 | try { 104 | constexpr std::size_t size = 10'000'000; 105 | 106 | for (std::uint8_t shard_bits = 1; shard_bits <= 8; ++shard_bits) { 107 | 108 | const std::uint32_t shards = 1U << shard_bits; 109 | const std::size_t shard_size = size / shards; 110 | 111 | std::cout << std::format("\n\nShard Size: {} Shards: {} Keys: {}\n\n", shard_size, shards, 112 | size); 113 | 114 | std::cout << std::format(" {:>8s} {:>8s} {:>8s} {:>8s} {:>8s} {:>8s}\n", "gen", 115 | "populate", "verify", "add", "query", "f+ve"); 116 | 117 | { 118 | binfuse::sharded_filter8_sink sink8("filter8.bin", shard_bits); 119 | populate(sink8, shards, shard_bits, shard_size); 120 | } 121 | { 122 | binfuse::sharded_filter8_source source8("filter8.bin", shard_bits); 123 | query(source8, size); 124 | } 125 | { 126 | binfuse::sharded_filter16_sink sink16("filter16.bin", shard_bits); 127 | populate(sink16, shards, shard_bits, shard_size); 128 | } 129 | { 130 | binfuse::sharded_filter16_source source16("filter16.bin", shard_bits); 131 | query(source16, size); 132 | } 133 | std::filesystem::remove("filter8.bin"); 134 | std::filesystem::remove("filter16.bin"); 135 | } 136 | } catch (const std::exception& e) { 137 | std::cerr << e.what() << "\n"; 138 | return EXIT_FAILURE; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /test/filter.cpp: -------------------------------------------------------------------------------- 1 | #include "binfuse/filter.hpp" 2 | #include "binaryfusefilter.h" 3 | #include "helpers.hpp" 4 | #include "gtest/gtest.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | TEST(binfuse_filter, default_construct) { // NOLINT 12 | binfuse::filter8 filter; 13 | EXPECT_FALSE(filter.is_populated()); 14 | } 15 | 16 | TEST(binfuse_filter, construct_from_upstream) { // NOLINT 17 | binary_fuse8_t fil; 18 | binary_fuse8_allocate(3, &fil); 19 | std::vector data{ 20 | 0x0000000000000000, 21 | 0x0000000000000001, 22 | 0x0000000000000002, 23 | }; 24 | binary_fuse8_populate(data.data(), static_cast(data.size()), &fil); 25 | 26 | binfuse::filter8 filter(std::move(fil)); // NOLINT not trivial 27 | EXPECT_TRUE(filter.is_populated()); 28 | EXPECT_EQ(filter.size(), 3); 29 | EXPECT_TRUE(filter.contains(0x0000000000000000)); 30 | EXPECT_TRUE(filter.contains(0x0000000000000001)); 31 | EXPECT_TRUE(filter.contains(0x0000000000000002)); 32 | } 33 | 34 | TEST(binfuse_filter, default_construct_persistent) { // NOLINT 35 | binfuse::filter8_sink filter_sink; 36 | EXPECT_FALSE(filter_sink.is_populated()); 37 | 38 | binfuse::filter8_source filter_source; 39 | EXPECT_FALSE(filter_source.is_populated()); 40 | } 41 | 42 | TEST(binfuse_filter, in_memory) { // NOLINT 43 | binfuse::filter8 filter(std::vector{ 44 | 0x0000000000000000, 45 | 0x0000000000000001, // order is not important 46 | 0x0000000000000002, 47 | }); 48 | EXPECT_TRUE(filter.is_populated()); 49 | 50 | EXPECT_TRUE(filter.contains(0x0000000000000000)); 51 | EXPECT_TRUE(filter.contains(0x0000000000000001)); 52 | EXPECT_TRUE(filter.contains(0x0000000000000002)); 53 | } 54 | 55 | TEST(binfuse_filter, save_load8) { // NOLINT 56 | { 57 | binfuse::filter8_sink filter_sink(std::vector{ 58 | 0x0000000000000000, 59 | 0x0000000000000001, // order is not important 60 | 0x0000000000000002, 61 | }); 62 | filter_sink.save("tmp/filter8.bin"); 63 | 64 | binfuse::filter8_source filter_source; 65 | filter_source.load("tmp/filter8.bin"); 66 | 67 | EXPECT_TRUE(filter_source.contains(0x0000000000000000)); 68 | EXPECT_TRUE(filter_source.contains(0x0000000000000001)); 69 | EXPECT_TRUE(filter_source.contains(0x0000000000000002)); 70 | } 71 | std::filesystem::remove("tmp/filter8.bin"); 72 | } 73 | 74 | TEST(binfuse_filter, save_load16) { // NOLINT 75 | { 76 | binfuse::filter16_sink filter_sink(std::vector{ 77 | 0x0000000000000000, 78 | 0x0000000000000001, // order is not important 79 | 0x0000000000000002, 80 | }); 81 | filter_sink.save("tmp/filter16.bin"); 82 | 83 | binfuse::filter16_source filter_source; 84 | filter_source.load("tmp/filter16.bin"); 85 | 86 | EXPECT_TRUE(filter_source.contains(0x0000000000000000)); 87 | EXPECT_TRUE(filter_source.contains(0x0000000000000001)); 88 | EXPECT_TRUE(filter_source.contains(0x0000000000000002)); 89 | } 90 | std::filesystem::remove("tmp/filter16.bin"); 91 | } 92 | 93 | TEST(binfuse_filter, move) { // NOLINT 94 | { 95 | binfuse::filter8_sink filter_sink(std::vector{ 96 | 0x0000000000000000, 97 | 0x0000000000000001, // order is not important 98 | 0x0000000000000002, 99 | }); 100 | filter_sink.save("tmp/filter8.bin"); 101 | 102 | binfuse::filter8_source filter_source; 103 | filter_source.load("tmp/filter8.bin"); 104 | 105 | binfuse::filter8_source filter_source2 = std::move(filter_source); 106 | 107 | EXPECT_TRUE(filter_source2.contains(0x0000000000000000)); 108 | EXPECT_TRUE(filter_source2.contains(0x0000000000000001)); 109 | EXPECT_TRUE(filter_source2.contains(0x0000000000000002)); 110 | } 111 | std::filesystem::remove("tmp/filter8.bin"); 112 | } 113 | 114 | // larger data tests 115 | 116 | TEST(binfuse_filter, large8) { // NOLINT 117 | auto keys = load_sample(); 118 | auto filter = binfuse::filter(keys); 119 | EXPECT_TRUE(filter.verify(keys)); 120 | EXPECT_LE(estimate_false_positive_rate(filter), 0.005); 121 | } 122 | 123 | TEST(binfuse_filter, large16) { // NOLINT 124 | auto keys = load_sample(); 125 | auto filter = binfuse::filter(keys); 126 | EXPECT_TRUE(filter.verify(keys)); 127 | EXPECT_LE(estimate_false_positive_rate(filter), 0.00005); 128 | } 129 | 130 | TEST(binfuse_filter, large8_persistent) { // NOLINT 131 | auto keys = load_sample(); 132 | const std::filesystem::path filter_path("tmp/filter.bin"); 133 | { 134 | auto filter_sink = binfuse::filter8_sink(keys); 135 | filter_sink.save(filter_path); 136 | auto filter_source = binfuse::filter8_source(); 137 | filter_source.load(filter_path); 138 | EXPECT_TRUE(filter_source.verify(keys)); 139 | EXPECT_LE(estimate_false_positive_rate(filter_source), 0.005); 140 | } 141 | std::filesystem::remove(filter_path); 142 | } 143 | 144 | TEST(binfuse_filter, large16_persistent) { // NOLINT 145 | auto keys = load_sample(); 146 | const std::filesystem::path filter_path("tmp/filter.bin"); 147 | { 148 | auto filter_sink = binfuse::filter16_sink(keys); 149 | filter_sink.save(filter_path); 150 | auto filter_source = binfuse::filter16_source(); 151 | filter_source.load(filter_path); 152 | EXPECT_TRUE(filter_source.verify(keys)); 153 | EXPECT_LE(estimate_false_positive_rate(filter_source), 0.00005); 154 | } 155 | std::filesystem::remove(filter_path); 156 | } 157 | -------------------------------------------------------------------------------- /include/binfuse/filter.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "binaryfusefilter.h" 4 | #include "mio/mmap.hpp" 5 | #include "mio/page.hpp" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | namespace binfuse { 22 | 23 | template 24 | concept filter_type = std::same_as || std::same_as; 25 | 26 | // select which functions on the C-API will be called with specialisations of the function ptrs 27 | 28 | template 29 | struct ftype {}; 30 | 31 | template <> 32 | struct ftype { 33 | static constexpr auto* allocate = binary_fuse8_allocate; 34 | static constexpr auto* populate = binary_fuse8_populate; 35 | static constexpr auto* contains = binary_fuse8_contain; 36 | static constexpr auto* free = binary_fuse8_free; 37 | static constexpr auto* serialization_bytes = binary_fuse8_serialization_bytes; 38 | static constexpr auto* serialize = binary_fuse8_serialize; 39 | static constexpr auto* deserialize_header = binary_fuse8_deserialize_header; 40 | using fingerprint_t = std::uint8_t; 41 | }; 42 | 43 | template <> 44 | struct ftype { 45 | static constexpr auto* allocate = binary_fuse16_allocate; 46 | static constexpr auto* populate = binary_fuse16_populate; 47 | static constexpr auto* contains = binary_fuse16_contain; 48 | static constexpr auto* free = binary_fuse16_free; 49 | static constexpr auto* serialization_bytes = binary_fuse16_serialization_bytes; 50 | static constexpr auto* serialize = binary_fuse16_serialize; 51 | static constexpr auto* deserialize_header = binary_fuse16_deserialize_header; 52 | using fingerprint_t = std::uint16_t; 53 | }; 54 | 55 | /* binfuse::filter 56 | * 57 | * wraps a single binary_fuse(8|16)_filter 58 | */ 59 | template 60 | class filter { 61 | public: 62 | static constexpr std::uint32_t nbits = sizeof(typename ftype::fingerprint_t) * 8; 63 | 64 | filter() = default; 65 | explicit filter(std::span keys) { populate(keys); } 66 | 67 | // accepts an r-value reference of the upstream `binary_fuse(8|16)_filter` object 68 | // will take ownership of any allocated memory pointed to by the `Fingerprints` member 69 | // will free that memory when this object is destroyed 70 | // NOLINTNEXTLINE don't move c-struct - would be misleading 71 | explicit filter(FilterType&& fil) noexcept : fil_(fil) { 72 | fil.Fingerprints = nullptr; 73 | } 74 | 75 | filter(const filter& other) = delete; 76 | filter& operator=(const filter& rhs) = delete; 77 | 78 | filter(filter&& other) noexcept 79 | : fil_(other.fil_), skip_free_fingerprints(other.skip_free_fingerprints) { 80 | other.fil_.Fingerprints = nullptr; // this object now owns any memory 81 | } 82 | filter& operator=(filter&& rhs) noexcept { 83 | if (this != &rhs) *this = fil_(std::move(rhs)); 84 | return *this; 85 | } 86 | 87 | ~filter() { 88 | if (skip_free_fingerprints) { 89 | fil_.Fingerprints = nullptr; 90 | } 91 | ftype::free(&fil_); 92 | } 93 | 94 | void populate(std::span keys) { 95 | if (is_populated()) { 96 | throw std::runtime_error("filter is already populated. You must provide all data at once."); 97 | } 98 | 99 | if (!ftype::allocate(static_cast(keys.size()), &fil_)) { 100 | throw std::runtime_error("failed to allocate memory.\n"); 101 | } 102 | if (!ftype::populate( 103 | const_cast(keys.data()), // NOLINT const_cast until API changed 104 | static_cast(keys.size()), &fil_)) { 105 | throw std::runtime_error("failed to populate the filter"); 106 | } 107 | } 108 | 109 | [[nodiscard]] bool contains(std::uint64_t needle) const { 110 | if (!is_populated()) { 111 | throw std::runtime_error("filter is not populated."); 112 | } 113 | return ftype::contains(needle, &fil_); 114 | } 115 | 116 | [[nodiscard]] std::size_t size() const { 117 | return static_cast(fil_.Size); 118 | } 119 | 120 | [[nodiscard]] bool is_populated() const { return size() > 0; } 121 | 122 | [[nodiscard]] std::size_t serialization_bytes() const { 123 | // upstream API should be const 124 | return ftype::serialization_bytes(const_cast(&fil_)); 125 | } 126 | 127 | // caller provides and owns the buffer. Either malloc'd or a 128 | // writable mmap, typically. 129 | void serialize(char* buffer) const { ftype::serialize(&fil_, buffer); } 130 | 131 | // Caller provides and owns the buffer. The lifetime of the buffer 132 | // must exceed the lifetime of this object. 133 | // 134 | // Specifically the lifetime of the `fingerprints`, which follow the 135 | // basic struct members, must also exceed any calls to 136 | // `this->contains|verify` etc. If using an `mmap` to provide the 137 | // buffer, then the file must remain mapped while calling 138 | // `this->contains`. 139 | // 140 | // Not respecting this will likely result in segfaults. 141 | void deserialize(const char* buffer) { 142 | const char* fingerprints = ftype::deserialize_header(&fil_, buffer); 143 | 144 | // set the freshly deserialized object's Fingerprint ptr (which is 145 | // where the bulk of the data is), to the byte immediately AFTER 146 | // the block where header bytes were deserialized FROM. 147 | fil_.Fingerprints = // NOLINTNEXTLINE const_cast & rein_cast due to upstream API 148 | reinterpret_cast::fingerprint_t*>(const_cast(fingerprints)); 149 | 150 | skip_free_fingerprints = true; // do not attempt to free this external buffer (probably an mmap) 151 | } 152 | 153 | // Check that each of the provided keys are `contain`ed in the 154 | // filter. Any false negative, immediately returns false with a 155 | // message to std::cerr. 156 | [[nodiscard]] bool verify(std::span keys) const { 157 | for (auto key: keys) { 158 | if (!contains(key)) { 159 | std::cerr << "binfuse::filter::verify: Detected a false negative: " << std::hex 160 | << std::setfill('0') << std::setw(16) << key << '\n'; 161 | return false; 162 | } 163 | } 164 | return true; 165 | } 166 | 167 | private: 168 | FilterType fil_{}; 169 | bool skip_free_fingerprints = false; 170 | }; 171 | 172 | template 173 | class persistent_filter : public filter { 174 | 175 | public: 176 | using filter::filter; 177 | 178 | void save(std::filesystem::path filepath) 179 | requires(AccessMode == mio::access_mode::write) 180 | { 181 | filepath_ = std::move(filepath); 182 | if (!this->is_populated()) { 183 | throw std::runtime_error("not populated. nothing to save"); 184 | } 185 | ensure_file(); 186 | auto filesize = header_length + this->serialization_bytes(); 187 | std::filesystem::resize_file(filepath_, filesize); 188 | map_whole_file(); 189 | create_filetag(); 190 | this->serialize(&mmap_[header_length]); 191 | sync(); 192 | } 193 | 194 | void load(std::filesystem::path filepath) 195 | requires(AccessMode == mio::access_mode::read) 196 | { 197 | filepath_ = std::move(filepath); 198 | map_whole_file(); 199 | check_type_id(); 200 | this->deserialize(&mmap_[header_length]); 201 | } 202 | 203 | private: 204 | mio::basic_mmap mmap_; 205 | std::filesystem::path filepath_; 206 | 207 | using offset_t = std::size_t; 208 | 209 | static constexpr std::size_t header_start = 0; 210 | static constexpr std::size_t header_length = 16; 211 | 212 | static constexpr std::size_t index_start = header_start + header_length; 213 | 214 | void copy_str_to_map(std::string value, offset_t offset) 215 | requires(AccessMode == mio::access_mode::write) 216 | { 217 | memcpy(&mmap_[offset], value.data(), value.size()); 218 | } 219 | 220 | [[nodiscard]] std::string get_str_from_map(offset_t offset, std::size_t strsize) const { 221 | std::string value; 222 | value.resize(strsize); 223 | memcpy(value.data(), &mmap_[offset], strsize); 224 | return value; 225 | } 226 | 227 | [[nodiscard]] std::string type_id() const { 228 | std::string type_id; 229 | std::stringstream type_id_stream(type_id); 230 | type_id_stream << "binfuse" << std::setfill('0') << std::setw(2) << this->nbits; 231 | return type_id_stream.str(); 232 | } 233 | 234 | void sync() 235 | requires(AccessMode == mio::access_mode::write) 236 | { 237 | std::error_code err; 238 | mmap_.sync(err); // ensure any existing map is sync'd 239 | if (err) { 240 | throw std::runtime_error("sharded_bin_fuse_filter:: mmap.map(): " + err.message()); 241 | } 242 | } 243 | 244 | void map_whole_file() { 245 | std::error_code err; 246 | mmap_.map(filepath_.string(), err); // does unmap then remap 247 | if (err) { 248 | throw std::runtime_error("sharded_bin_fuse_filter:: mmap.map(): " + err.message()); 249 | } 250 | } 251 | 252 | void check_type_id() const { 253 | auto tid = type_id(); 254 | auto check_tid = get_str_from_map(0, tid.size()); 255 | if (check_tid != tid) { 256 | throw std::runtime_error("incorrect type_id: expected: " + tid + ", found: " + check_tid); 257 | } 258 | } 259 | 260 | // returns existing file size 261 | std::uintmax_t ensure_file() 262 | requires(AccessMode == mio::access_mode::write) 263 | { 264 | if (filepath_.empty()) { 265 | throw std::runtime_error("filename not set or file doesn't exist: '" + filepath_.string() + 266 | "'"); 267 | } 268 | 269 | std::uintmax_t existing_filesize = 0; 270 | if (std::filesystem::exists(filepath_)) { 271 | existing_filesize = std::filesystem::file_size(filepath_); 272 | } else { 273 | const std::ofstream tmp(filepath_); // "touch" 274 | } 275 | return existing_filesize; 276 | } 277 | 278 | void create_filetag() 279 | requires(AccessMode == mio::access_mode::write) 280 | { 281 | copy_str_to_map(type_id(), 0); 282 | } 283 | }; 284 | 285 | using filter8 = filter; 286 | using filter16 = filter; 287 | 288 | using filter8_sink = persistent_filter; 289 | using filter8_source = persistent_filter; 290 | 291 | using filter16_sink = persistent_filter; 292 | using filter16_source = persistent_filter; 293 | 294 | } // namespace binfuse 295 | -------------------------------------------------------------------------------- /test/sharded_filter.cpp: -------------------------------------------------------------------------------- 1 | #include "binfuse/sharded_filter.hpp" 2 | #include "binaryfusefilter.h" 3 | #include "binfuse/filter.hpp" 4 | #include "helpers.hpp" 5 | #include "mio/page.hpp" 6 | #include "gtest/gtest.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | TEST(binfuse_sfilter, default_construct) { // NOLINT 14 | binfuse::sharded_filter8_source sharded_source; 15 | EXPECT_EQ(sharded_source.shards(), 0); 16 | } 17 | 18 | TEST(binfuse_sfilter, add_tiny) { // NOLINT 19 | { 20 | binfuse::filter8 tiny_low(std::vector{ 21 | // note the MSB is clear on all below 22 | 0x0000000000000000, 23 | 0x0000000000000001, // order is not important 24 | 0x0000000000000002, 25 | }); 26 | 27 | binfuse::filter8 tiny_high(std::vector{ 28 | // note the MSB is set on all below 29 | 0x8000000000000000, 30 | 0x8000000000000001, // order is not important 31 | 0x8000000000000002, 32 | }); 33 | 34 | binfuse::sharded_filter8_sink sink("tmp/sharded_filter8_tiny.bin", 35 | 1); // one bit sharding, ie 2 shards 36 | 37 | sink.add_shard(tiny_low, 0); // specify the prefix for each shard 38 | sink.add_shard(tiny_high, 1); // order of adding is not important 39 | 40 | EXPECT_EQ(sink.shards(), 2); 41 | 42 | // now reopen the filter as a "source" 43 | binfuse::sharded_filter8_source source("tmp/sharded_filter8_tiny.bin", 1); 44 | 45 | // verify all entries 46 | EXPECT_TRUE(source.contains(0x0000000000000000)); 47 | EXPECT_TRUE(source.contains(0x0000000000000001)); 48 | EXPECT_TRUE(source.contains(0x0000000000000002)); 49 | EXPECT_TRUE(source.contains(0x8000000000000000)); 50 | EXPECT_TRUE(source.contains(0x8000000000000001)); 51 | EXPECT_TRUE(source.contains(0x8000000000000002)); 52 | 53 | EXPECT_EQ(source.shards(), 2); 54 | } 55 | // cleanup 56 | std::filesystem::remove("tmp/sharded_filter8_tiny.bin"); 57 | } 58 | 59 | TEST(binfuse_sfilter, add_ooo) { // NOLINT 60 | { 61 | binfuse::filter8 tiny_low( // out of order elements are permissible 62 | std::vector{0x0000000000000002, 0x0000000000000000, 0x0000000000000001}); 63 | 64 | binfuse::filter8 tiny_high( // out of order elements are permissible 65 | std::vector{0x8000000000000001, 0x8000000000000002, 0x8000000000000000}); 66 | 67 | binfuse::sharded_filter sink( 68 | "tmp/sharded_filter8_tiny.bin", 1); 69 | 70 | // adding shards out of order is also permissible, alhtough may result in 71 | // very slightly suboptimal disk layout of the filter 72 | sink.add_shard(tiny_high, 1); 73 | sink.add_shard(tiny_low, 0); 74 | 75 | binfuse::sharded_filter source( 76 | "tmp/sharded_filter8_tiny.bin", 1); 77 | 78 | EXPECT_TRUE(source.contains(0x0000000000000000)); 79 | EXPECT_TRUE(source.contains(0x0000000000000001)); 80 | EXPECT_TRUE(source.contains(0x0000000000000002)); 81 | EXPECT_TRUE(source.contains(0x8000000000000000)); 82 | EXPECT_TRUE(source.contains(0x8000000000000001)); 83 | EXPECT_TRUE(source.contains(0x8000000000000002)); 84 | } 85 | std::filesystem::remove("tmp/sharded_filter8_tiny.bin"); 86 | } 87 | 88 | TEST(binfuse_sfilter, missing_shard) { // NOLINT 89 | { 90 | binfuse::filter8 tiny_high( 91 | std::vector{0x8000000000000000, 0x8000000000000001, 0x8000000000000002}); 92 | 93 | binfuse::sharded_filter sink( 94 | "tmp/sharded_filter8_tiny.bin", 1); 95 | 96 | // only add a `high` shard with prefix = 1, omit prefix = 0 97 | sink.add_shard(tiny_high, 1); 98 | EXPECT_EQ(sink.shards(), 1); 99 | 100 | binfuse::sharded_filter source( 101 | "tmp/sharded_filter8_tiny.bin", 1); 102 | 103 | // try to find an element in the missing low shard => always false 104 | EXPECT_FALSE(source.contains(0x0000000000000000)); 105 | } 106 | std::filesystem::remove("tmp/sharded_filter8_tiny.bin"); 107 | } 108 | 109 | TEST(binfuse_sfilter, empty_shard) { // NOLINT 110 | { 111 | binfuse::filter8 tiny_high(std::vector{}); 112 | 113 | binfuse::sharded_filter sink( 114 | "tmp/sharded_filter8_tiny.bin", 1); 115 | 116 | // only add a `high` shard with prefix = 1, omit prefix = 0 117 | sink.add_shard(tiny_high, 1); 118 | 119 | binfuse::sharded_filter source( 120 | "tmp/sharded_filter8_tiny.bin", 1); 121 | 122 | // try to find an element in the missing low shard 123 | EXPECT_FALSE(source.contains(0x8000000000000000)); 124 | } 125 | std::filesystem::remove("tmp/sharded_filter8_tiny.bin"); 126 | } 127 | 128 | TEST(binfuse_sfilter, read_sink_directly) { // NOLINT 129 | { 130 | binfuse::filter8 tiny_low(std::vector{ 131 | // note the MSB is clear on all below 132 | 0x0000000000000000, 133 | 0x0000000000000001, // order is not important 134 | 0x0000000000000002, 135 | }); 136 | 137 | binfuse::filter8 tiny_high(std::vector{ 138 | // note the MSB is set on all below 139 | 0x8000000000000000, 140 | 0x8000000000000001, // order is not important 141 | 0x8000000000000002, 142 | }); 143 | 144 | binfuse::sharded_filter8_sink sink("tmp/sharded_filter8_tiny.bin", 145 | 1); // one bit sharding, ie 2 shards 146 | 147 | sink.add_shard(tiny_low, 0); // specify the prefix for each shard 148 | sink.add_shard(tiny_high, 1); // order of adding is not important 149 | 150 | // verify all entries directly in sink 151 | EXPECT_TRUE(sink.contains(0x0000000000000000)); 152 | EXPECT_TRUE(sink.contains(0x0000000000000001)); 153 | EXPECT_TRUE(sink.contains(0x0000000000000002)); 154 | EXPECT_TRUE(sink.contains(0x8000000000000000)); 155 | EXPECT_TRUE(sink.contains(0x8000000000000001)); 156 | EXPECT_TRUE(sink.contains(0x8000000000000002)); 157 | 158 | EXPECT_EQ(sink.shards(), 2); 159 | } 160 | // cleanup 161 | std::filesystem::remove("tmp/sharded_filter8_tiny.bin"); 162 | } 163 | 164 | TEST(binfuse_sfilter, read_sink_after_load) { // NOLINT 165 | { 166 | binfuse::filter8 tiny_low(std::vector{ 167 | // note the MSB is clear on all below 168 | 0x0000000000000000, 169 | 0x0000000000000001, // order is not important 170 | 0x0000000000000002, 171 | }); 172 | 173 | binfuse::filter8 tiny_high(std::vector{ 174 | // note the MSB is set on all below 175 | 0x8000000000000000, 176 | 0x8000000000000001, // order is not important 177 | 0x8000000000000002, 178 | }); 179 | 180 | binfuse::sharded_filter8_sink sink("tmp/sharded_filter8_tiny.bin", 1); 181 | 182 | sink.add_shard(tiny_low, 0); 183 | sink.add_shard(tiny_high, 1); 184 | 185 | binfuse::sharded_filter8_sink sink2("tmp/sharded_filter8_tiny.bin", 1); 186 | // verify all entries directly in sink 187 | EXPECT_TRUE(sink2.contains(0x0000000000000000)); 188 | EXPECT_TRUE(sink2.contains(0x0000000000000001)); 189 | EXPECT_TRUE(sink2.contains(0x0000000000000002)); 190 | EXPECT_TRUE(sink2.contains(0x8000000000000000)); 191 | EXPECT_TRUE(sink2.contains(0x8000000000000001)); 192 | EXPECT_TRUE(sink2.contains(0x8000000000000002)); 193 | 194 | EXPECT_EQ(sink.shards(), 2); 195 | } 196 | // cleanup 197 | std::filesystem::remove("tmp/sharded_filter8_tiny.bin"); 198 | } 199 | 200 | TEST(binfuse_sfilter, stream_tiny) { // NOLINT 201 | { 202 | binfuse::sharded_filter sink( 203 | "tmp/sharded_filter8_tiny.bin", 1); 204 | 205 | // alternative "streaming" API for bullding the filter 206 | // the entries below must be strictly in order 207 | sink.stream_prepare(); 208 | sink.stream_add(0x0000000000000000); 209 | sink.stream_add(0x0000000000000001); 210 | sink.stream_add(0x0000000000000002); 211 | sink.stream_add(0x8000000000000000); 212 | sink.stream_add(0x8000000000000001); 213 | sink.stream_add(0x8000000000000002); 214 | sink.stream_finalize(); 215 | 216 | binfuse::sharded_filter source( 217 | "tmp/sharded_filter8_tiny.bin", 1); 218 | 219 | EXPECT_TRUE(source.contains(0x0000000000000000)); 220 | EXPECT_TRUE(source.contains(0x0000000000000001)); 221 | EXPECT_TRUE(source.contains(0x0000000000000002)); 222 | EXPECT_TRUE(source.contains(0x8000000000000000)); 223 | EXPECT_TRUE(source.contains(0x8000000000000001)); 224 | EXPECT_TRUE(source.contains(0x8000000000000002)); 225 | } 226 | std::filesystem::remove("tmp/sharded_filter8_tiny.bin"); 227 | } 228 | 229 | TEST(binfuse_sfilter, stream_ooo) { // NOLINT 230 | binfuse::sharded_filter8_sink sink("tmp/sharded_filter8_tiny.bin", 1); 231 | 232 | // alternative "streaming" API for bullding the filter 233 | // the entries below must be strictly in order 234 | sink.stream_prepare(); 235 | sink.stream_add(0x0000000000000001); 236 | // out of order add 237 | EXPECT_THROW(sink.stream_add(0x0000000000000000), std::runtime_error); 238 | } 239 | 240 | TEST(binfuse_sfilter, load_tiny) { // NOLINT 241 | binfuse::sharded_filter8_source source; 242 | EXPECT_THROW(source.set_filename("non_existant.bin"), std::runtime_error); 243 | 244 | // wrong `shard_bits`.. which defaults to `8`, but file ws created with `2` 245 | EXPECT_THROW(source.set_filename("data/sharded_filter8_tiny.bin"), std::runtime_error); 246 | 247 | source.set_filename("data/sharded_filter8_tiny.bin", 1); // correct capacity 248 | 249 | EXPECT_TRUE(source.contains(0x0000000000000002)); 250 | EXPECT_TRUE(source.contains(0x8000000000000000)); 251 | } 252 | 253 | // larger data tests 254 | 255 | template 256 | void test_sharded_filter(std::span keys, double max_false_positive_rate, 257 | uint8_t sharded_bits = 8) { 258 | std::filesystem::path filter_filename; 259 | filter_filename = "tmp/sharded_filter.bin"; 260 | { 261 | binfuse::sharded_filter sharded_sink(filter_filename, 262 | sharded_bits); 263 | sharded_sink.stream_prepare(); 264 | for (auto key: keys) { 265 | sharded_sink.stream_add(key); 266 | } 267 | sharded_sink.stream_finalize(); 268 | 269 | const binfuse::sharded_filter sharded_source( 270 | filter_filename, sharded_bits); 271 | 272 | // full verify across all shards 273 | for (auto needle: keys) { 274 | EXPECT_TRUE(sharded_source.contains(needle)); 275 | } 276 | EXPECT_LE(estimate_false_positive_rate(sharded_source), max_false_positive_rate); 277 | } // allow mmap to be destroy before removing file (required on windows) 278 | 279 | std::filesystem::remove(filter_filename); 280 | } 281 | 282 | TEST(binfuse_sfilter, large8) { // NOLINT 283 | test_sharded_filter(load_sample(), 0.005); 284 | } 285 | 286 | TEST(binfuse_sfilter, large16) { // NOLINT 287 | test_sharded_filter(load_sample(), 0.00005); 288 | } 289 | 290 | TEST(binfuse_sfilter, large8_32) { // NOLINT 291 | test_sharded_filter(load_sample(), 0.005, 5); // 5 sharded_bits 292 | } 293 | 294 | TEST(binfuse_sfilter, large16_32) { // NOLINT 295 | test_sharded_filter(load_sample(), 0.00005, 5); // 5 sharded_bits 296 | } 297 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /include/binfuse/sharded_filter.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "binaryfusefilter.h" 4 | #include "binfuse/filter.hpp" 5 | #include "mio/mmap.hpp" 6 | #include "mio/page.hpp" 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | namespace binfuse { 22 | 23 | // selecting the appropriate map for the access mode 24 | template 25 | struct sharded_mmap_base { 26 | mio::basic_mmap mmap; 27 | using mmap_size_type = typename decltype(mmap)::size_type; 28 | }; 29 | 30 | /* sharded_bin_fuse_filter. 31 | * 32 | * Wraps a set of `binfuse::filter`s. 33 | * Saves/loads them to/from an mmap'd file via mio::mmap. 34 | * Directs `contains` queries to the apropriate sub-filter. 35 | * 36 | */ 37 | template 38 | class sharded_filter : private sharded_mmap_base { 39 | public: 40 | using shard_filter_t = filter; 41 | 42 | static constexpr std::uint32_t nbits = sizeof(typename ftype::fingerprint_t) * 8; 43 | 44 | sharded_filter() = default; 45 | explicit sharded_filter(std::filesystem::path path, std::uint8_t shard_bits = 8) 46 | : filepath_(std::move(path)), shard_bits_(shard_bits) { 47 | load(); 48 | } 49 | 50 | // make a default constructor possible 51 | void set_filename(std::filesystem::path path, std::uint8_t shard_bits = 8) { 52 | filepath_ = std::move(path); 53 | shard_bits_ = shard_bits; 54 | load(); 55 | } 56 | 57 | [[nodiscard]] bool contains(std::uint64_t needle) const { 58 | const auto prefix = extract_prefix(needle); 59 | // we know prefix is always < max_shards() by definition 60 | const auto& filter = filters[prefix]; 61 | if (!filter.is_populated()) { 62 | // this filter has not been populated. no fingerprint pointer 63 | // has been set and an upstream `contain` call will throw 64 | return false; 65 | } 66 | return filter.contains(needle); 67 | } 68 | 69 | [[nodiscard]] std::uint32_t extract_prefix(std::uint64_t key) const { 70 | return static_cast(key >> (sizeof(key) * 8 - shard_bits_)); 71 | } 72 | 73 | void stream_prepare() 74 | requires(AccessMode == mio::access_mode::write) 75 | { 76 | stream_keys_.clear(); 77 | stream_last_prefix_ = 0; 78 | stream_last_key_ = 0; 79 | } 80 | 81 | void stream_add(std::uint64_t key) 82 | requires(AccessMode == mio::access_mode::write) 83 | { 84 | if (key < stream_last_key_) { 85 | throw std::runtime_error("sharded_filter: stream_add: key out of order"); 86 | } 87 | stream_last_key_ = key; 88 | auto prefix = extract_prefix(key); 89 | if (prefix != stream_last_prefix_) { 90 | 91 | add_shard(shard_filter_t(stream_keys_), stream_last_prefix_); 92 | stream_keys_.clear(); 93 | stream_last_prefix_ = prefix; 94 | } 95 | stream_keys_.emplace_back(key); 96 | } 97 | 98 | void stream_finalize() 99 | requires(AccessMode == mio::access_mode::write) 100 | { 101 | if (!stream_keys_.empty()) { 102 | add_shard(shard_filter_t(stream_keys_), stream_last_prefix_); 103 | } 104 | } 105 | 106 | void add_shard(const shard_filter_t& new_filter, std::uint32_t prefix) 107 | requires(AccessMode == mio::access_mode::write) 108 | { 109 | if (shards_ == max_shards()) { 110 | throw std::runtime_error("sharded filter has reached max_shards of " + 111 | std::to_string(max_shards())); 112 | } 113 | 114 | std::uintmax_t new_size = ensure_header(); 115 | 116 | const std::size_t size_req = new_filter.serialization_bytes(); 117 | const offset_t new_filter_offset = new_size; // place new filter at end 118 | new_size += size_req; 119 | 120 | sync(); 121 | std::filesystem::resize_file(filepath_, new_size); 122 | map_whole_file(); 123 | 124 | auto old_filter_offset = get_from_map(filter_index_offset(prefix)); 125 | 126 | if (old_filter_offset != empty_offset) { 127 | throw std::runtime_error("there is already a filter in this file for prefix = " + 128 | std::to_string(prefix)); 129 | } 130 | copy_to_map(new_filter_offset, filter_index_offset(prefix)); // set up the index ptr 131 | new_filter.serialize( 132 | &this->mmap[static_cast(new_filter_offset)]); // insert the data 133 | index[prefix] = new_filter_offset; 134 | ++shards_; 135 | sync(); // save all changes 136 | // because has been re-mapped above, need to reload all filters as ptrs to 137 | // Fingerprints will likely have changed 138 | load_filters(); 139 | } 140 | 141 | [[nodiscard]] std::size_t shards() const { return shards_; } 142 | [[nodiscard]] std::size_t size() const { return size_; } 143 | 144 | private: 145 | std::vector index; 146 | std::vector filters; 147 | std::filesystem::path filepath_; 148 | std::uint8_t shard_bits_ = 8; 149 | std::uint32_t shards_ = 0; 150 | std::uint64_t size_ = 0; 151 | 152 | std::vector stream_keys_; 153 | std::uint32_t stream_last_prefix_ = 0; 154 | std::uint64_t stream_last_key_ = 0; 155 | 156 | using offset_t = typename decltype(index)::value_type; 157 | using mmap_size_t = sharded_mmap_base::mmap_size_type; 158 | static constexpr auto empty_offset = static_cast(-1); 159 | 160 | /* 161 | * `binfuse::sharded_filter` has to be file backed, because data is 162 | * presumably large enough to not fit in memory at least during 163 | * filter build (otherwise use a binfuse::filter) 164 | * 165 | * file structure is as follows: 166 | * 167 | * header [0 -> 16) : small number of bytes identifying the type of file, the 168 | * type of filters contained and how many shards are contained. 169 | * 170 | * index [16 -> 16 + 8 * max_shards() ): table of offsets to each 171 | * filter in the body. The offsets in the table are relative to the 172 | * start of the file. 173 | * 174 | * body [16 + 8 * max_shards() -> end ): the filters: each one has 175 | * the filter_struct_fields (ie the "header") followed by the large 176 | * array of (8 or 16bit) fingerprints. The offsets in the index will 177 | * point the start of the filter_heade, so that deserialize can be 178 | * called directly on that. 179 | * 180 | */ 181 | 182 | static constexpr std::size_t header_start = 0; 183 | static constexpr std::size_t header_length = 16; 184 | 185 | static constexpr std::size_t index_start = header_start + header_length; 186 | 187 | template 188 | void copy_to_map(T value, offset_t offset) 189 | requires(AccessMode == mio::access_mode::write) 190 | { 191 | memcpy(&this->mmap[static_cast(offset)], &value, sizeof(T)); 192 | } 193 | 194 | void copy_str_to_map(std::string value, offset_t offset) 195 | requires(AccessMode == mio::access_mode::write) 196 | { 197 | memcpy(&this->mmap[static_cast(offset)], value.data(), value.size()); 198 | } 199 | 200 | template 201 | [[nodiscard]] T get_from_map(offset_t offset) const { 202 | T value; 203 | memcpy(&value, &this->mmap[static_cast(offset)], sizeof(T)); 204 | return value; 205 | } 206 | 207 | [[nodiscard]] std::string get_str_from_map(offset_t offset, std::size_t strsize) const { 208 | std::string value; 209 | value.resize(strsize); 210 | memcpy(value.data(), &this->mmap[static_cast(offset)], strsize); 211 | return value; 212 | } 213 | 214 | [[nodiscard]] std::uint32_t max_shards() const { return 1U << shard_bits_; } 215 | 216 | [[nodiscard]] std::size_t index_length() const { return sizeof(offset_t) * max_shards(); } 217 | 218 | [[nodiscard]] std::size_t filter_index_offset(std::uint32_t prefix) const { 219 | return index_start + sizeof(offset_t) * prefix; 220 | } 221 | 222 | [[nodiscard]] offset_t filter_offset(std::uint32_t prefix) const { 223 | return get_from_map(filter_index_offset(prefix)); 224 | } 225 | 226 | [[nodiscard]] std::string type_id() const { 227 | std::string type_id; 228 | std::stringstream type_id_stream(type_id); 229 | type_id_stream << "sbinfuse" << std::setfill('0') << std::setw(2) << nbits; 230 | return type_id_stream.str(); 231 | } 232 | 233 | void sync() 234 | requires(AccessMode == mio::access_mode::write) 235 | { 236 | std::error_code err; 237 | this->mmap.sync(err); // ensure any existing map is sync'd 238 | if (err) { 239 | throw std::runtime_error("sharded_bin_fuse_filter:: mmap.map(): " + err.message()); 240 | } 241 | } 242 | 243 | void map_whole_file() { 244 | std::error_code err; 245 | this->mmap.map(filepath_.string(), err); // does unmap then remap 246 | if (err) { 247 | throw std::runtime_error("sharded_bin_fuse_filter:: mmap.map(): " + err.message()); 248 | } 249 | } 250 | 251 | void check_type_id() const { 252 | auto tid = type_id(); 253 | auto check_tid = get_str_from_map(0, tid.size()); 254 | if (check_tid != tid) { 255 | throw std::runtime_error("incorrect type_id: expected: " + tid + ", found: " + check_tid); 256 | } 257 | } 258 | 259 | void check_max_shards() const { 260 | std::uint32_t check_max_shards = 0; 261 | std::from_chars(&this->mmap[11], &this->mmap[15], check_max_shards); 262 | if (check_max_shards != max_shards()) { 263 | throw std::runtime_error("wrong capacity: expected: " + std::to_string(max_shards()) + 264 | ", found: " + std::to_string(check_max_shards)); 265 | } 266 | } 267 | 268 | // returns existing file size 269 | std::uintmax_t ensure_file() 270 | requires(AccessMode == mio::access_mode::write) 271 | { 272 | if (filepath_.empty()) { 273 | throw std::runtime_error("filename not set or file doesn't exist: '" + filepath_.string() + 274 | "'"); 275 | } 276 | 277 | std::uintmax_t existing_filesize = 0; 278 | if (std::filesystem::exists(filepath_)) { 279 | existing_filesize = std::filesystem::file_size(filepath_); 280 | } else { 281 | const std::ofstream tmp(filepath_); // "touch" 282 | } 283 | return existing_filesize; 284 | } 285 | 286 | void create_filetag() 287 | requires(AccessMode == mio::access_mode::write) 288 | { 289 | std::string tagstr; 290 | std::stringstream tagstream(tagstr); 291 | tagstream << type_id() << '-' << std::setfill('0') << std::setw(4) << max_shards(); 292 | copy_str_to_map(tagstream.str(), 0); 293 | } 294 | 295 | void create_index() 296 | requires(AccessMode == mio::access_mode::write) 297 | { 298 | index.resize(max_shards(), empty_offset); 299 | memcpy(&this->mmap[index_start], index.data(), index.size() * sizeof(offset_t)); 300 | } 301 | 302 | void load_index() { 303 | index.resize(max_shards(), empty_offset); 304 | memcpy(index.data(), &this->mmap[index_start], index.size() * sizeof(offset_t)); 305 | shards_ = static_cast( 306 | count_if(index.begin(), index.end(), [](auto a) { return a != empty_offset; })); 307 | } 308 | 309 | void load_filters() { 310 | // always "load" all, even if as yet unpopulated 311 | filters.clear(); 312 | filters.resize(max_shards()); // default constructed, which zeroes all values 313 | for (uint32_t prefix = 0; prefix != max_shards(); ++prefix) { 314 | if (auto offset = index[prefix]; offset != empty_offset) { 315 | filters[prefix].deserialize(&this->mmap[static_cast(offset)]); 316 | } 317 | } 318 | } 319 | 320 | // only does something for AccessMode = read 321 | // if you write a filter, you must reopen it in read mode 322 | void load() { 323 | if constexpr (AccessMode == mio::access_mode::write) { 324 | if (!std::filesystem::exists(filepath_)) { 325 | ensure_file(); 326 | ensure_header(); 327 | return; 328 | } 329 | } 330 | map_whole_file(); // read mode will fail here if not exists 331 | check_type_id(); 332 | check_max_shards(); 333 | load_index(); 334 | load_filters(); 335 | } 336 | 337 | // returns new_filesize 338 | std::uintmax_t ensure_header() 339 | requires(AccessMode == mio::access_mode::write) 340 | { 341 | const std::uintmax_t existing_filesize = ensure_file(); 342 | std::uintmax_t new_size = existing_filesize; 343 | if (existing_filesize < header_length + index_length()) { 344 | if (existing_filesize != 0) { 345 | throw std::runtime_error("corrupt file: header and index half written?!"); 346 | } 347 | // existing_size == 0 here 348 | new_size += header_length + index_length(); 349 | std::filesystem::resize_file(filepath_, new_size); 350 | map_whole_file(); 351 | create_filetag(); 352 | create_index(); 353 | sync(); // write to disk 354 | load_filters(); 355 | shards_ = 0; 356 | } else { 357 | // we have a header already 358 | map_whole_file(); 359 | check_type_id(); 360 | check_max_shards(); 361 | load_index(); 362 | load_filters(); 363 | } 364 | return new_size; 365 | } 366 | }; 367 | 368 | // easy to use aliases 369 | using sharded_filter8_sink = sharded_filter; 370 | 371 | using sharded_filter8_source = sharded_filter; 372 | 373 | using sharded_filter16_sink = sharded_filter; 374 | 375 | using sharded_filter16_source = sharded_filter; 376 | 377 | } // namespace binfuse 378 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Ubuntu 24.04 (gcc-13, clang-18)](https://github.com/oschonrock/binfuse/actions/workflows/ubuntu.yml/badge.svg)](https://github.com/oschonrock/binfuse/actions/workflows/ubuntu.yml) 2 | [![Windows MINGW32/64 gcc/clang](https://github.com/oschonrock/binfuse/actions/workflows/msys2.yml/badge.svg)](https://github.com/oschonrock/binfuse/actions/workflows/msys2.yml) 3 | [![FreeBSD-14.1 clang-18.1](https://github.com/oschonrock/binfuse/actions/workflows/freebsd.yml/badge.svg)](https://github.com/oschonrock/binfuse/actions/workflows/freebsd.yml) 4 | 5 | # `binfuse` C++ Library for Binary Fuse Filters 6 | 7 | Binary fuse filters are a recent (2022) development in the group of 8 | [Approximate Membership Query filters](https://en.wikipedia.org/wiki/Approximate_membership_query_filter) 9 | 10 | > Approximate membership query filters (hereafter, AMQ filters) 11 | > comprise a group of space-efficient probabilistic data structures 12 | > that support approximate membership queries. An approximate 13 | > membership query answers whether an element is in a set or not with 14 | > a false positive rate of ϵ. 15 | 16 | Binary fuse filters are a further development of XOR filters. Both 17 | are more space efficient, and faster to build/query than traditional 18 | options like Bloom and Cuckoo filters. 19 | 20 | This [`binfuse` C++ library](https://github.com/oschonrock/binfuse) 21 | builds on the 22 | [C-libary](https://github.com/FastFilter/xor_singleheader) by the 23 | authors of the [relevant research 24 | paper](http://arxiv.org/abs/2201.01174). 25 | 26 | As well as adding a convenient C++ interface, `binfuse::filter` also 27 | facilitates (de-)serializing the populated filter to/from disk as well 28 | as querying it directly from disk via an `mmap`, with cross platform 29 | support from [mio](https://github.com/vimpunk/mio). Both in memory and 30 | "off disk" operation is supported. 31 | 32 | One of the challenges with binary fuse filters, is that they are 33 | immutable once populated, so data cannot be added incrementally, and 34 | they consume a significant amount of memory during the populate 35 | process - 64GB of memory is recommended for populating with 500 36 | million `uint64_t` keys/hashes. This has, until now, placed an upward 37 | bound on the practical application of these filters to very large 38 | datasets. 39 | 40 | `binfuse::sharded_filter` allows convenient slicing of the dataset 41 | into an arbitrary number of shards which are written to 42 | disk and indexed by the `N` most significant bits of the `uint64_t` 43 | keys/hashes. Sharding is transparent to the user during queries is and 44 | still very fast with just 3 `mmap` accesses per query. 45 | 46 | `binfuse::sharded_filter` easily controls RAM requirements during the 47 | "populate filter" process and enables datasets of 10s of billions of 48 | records with common hardware. Query speeds depend on disk hardware and 49 | cache conditions, but can be in the 50ns range. 50 | 51 | ## Applications 52 | 53 | The movitating use case was [this pwned pasword db 54 | project](https://github.com/oschonrock/hibp), but there are many 55 | [common 56 | applications](https://en.wikipedia.org/wiki/Approximate_membership_query_filter#Application): 57 | 58 | > Typical applications of AMQ filters are distributed systems and 59 | > database systems. The AMQ filter functions as a proxy to the set of 60 | > keys of a database or remote memory. Before a presumably slow query 61 | > to the database or to remote memory is performed, the AMQ filter is 62 | > used to give an approximate answer as to whether the key is in the 63 | > database or in remote memory. The slow query is only performed when 64 | > the AMQ filter returns true. Only in the case of a (hopefully rare) 65 | > false positive is an unnecessary I/O or remote access performed. The 66 | > applications are numerous and include package and resource routing, 67 | > P2P networks, and distributed caching. 68 | 69 | ## Usage examples from [tests](https://github.com/oschonrock/binfuse/tree/main/test) 70 | 71 | Singular `binuse::filter` for in memory use: 72 | 73 | ```C++ 74 | binfuse::filter8 filter(std::vector{ 75 | 0x0000000000000000, 76 | 0x0000000000000001, // order is not important 77 | 0x0000000000000002, 78 | }); 79 | EXPECT_TRUE(filter.is_populated()); 80 | 81 | EXPECT_TRUE(filter.contains(0x0000000000000000)); 82 | EXPECT_TRUE(filter.contains(0x0000000000000001)); 83 | EXPECT_TRUE(filter.contains(0x0000000000000002)); 84 | ``` 85 | 86 | Singular `binuse::filter` save and load: 87 | 88 | ```C++ 89 | binfuse::filter8_sink filter_sink(std::vector{ 90 | 0x0000000000000000, 91 | 0x0000000000000001, // order is not important 92 | 0x0000000000000002, 93 | }); 94 | filter_sink.save("tmp/filter8.bin"); 95 | 96 | binfuse::filter8_source filter_source; 97 | filter_source.load("tmp/filter8.bin"); 98 | 99 | EXPECT_TRUE(filter_source.contains(0x0000000000000000)); 100 | EXPECT_TRUE(filter_source.contains(0x0000000000000001)); 101 | EXPECT_TRUE(filter_source.contains(0x0000000000000002)); 102 | ``` 103 | 104 | Sharded filter, bulding one shard at the time: 105 | 106 | ```C++ 107 | binfuse::filter8 tiny_low(std::vector{ 108 | // note the MSB is clear on all below 109 | 0x0000000000000000, 110 | 0x0000000000000001, // order is not important 111 | 0x0000000000000002, 112 | }); 113 | 114 | binfuse::filter8 tiny_high(std::vector{ 115 | // note the MSB is set on all below 116 | 0x8000000000000000, 117 | 0x8000000000000001, // order is not important 118 | 0x8000000000000002, 119 | }); 120 | 121 | binfuse::sharded_filter8_sink sink("tmp/sharded_filter8_tiny.bin", 122 | 1); // one bit sharding, ie 2 shards 123 | 124 | sink.add_shard(tiny_low, 0); // specify the prefix for each shard 125 | sink.add_shard(tiny_high, 1); // order of adding is not important 126 | 127 | EXPECT_EQ(sink.shards(), 2); 128 | 129 | // now reopen the filter as a "source" 130 | binfuse::sharded_filter8_source source("tmp/sharded_filter8_tiny.bin", 1); 131 | 132 | // verify all entries 133 | EXPECT_TRUE(source.contains(0x0000000000000000)); 134 | EXPECT_TRUE(source.contains(0x0000000000000001)); 135 | EXPECT_TRUE(source.contains(0x0000000000000002)); 136 | EXPECT_TRUE(source.contains(0x8000000000000000)); 137 | EXPECT_TRUE(source.contains(0x8000000000000001)); 138 | EXPECT_TRUE(source.contains(0x8000000000000002)); 139 | 140 | EXPECT_EQ(source.shards(), 2); 141 | ``` 142 | 143 | or via "streaming" API: 144 | 145 | ```C++ 146 | binfuse::sharded_filter sink( 147 | "tmp/sharded_filter8_tiny.bin", 1); 148 | 149 | // alternative "streaming" API for bullding the filter 150 | // the entries below must be strictly in order 151 | sink.stream_prepare(); 152 | sink.stream_add(0x0000000000000000); 153 | sink.stream_add(0x0000000000000001); 154 | sink.stream_add(0x0000000000000002); 155 | sink.stream_add(0x8000000000000000); 156 | sink.stream_add(0x8000000000000001); 157 | sink.stream_add(0x8000000000000002); 158 | sink.stream_finalize(); 159 | 160 | binfuse::sharded_filter source( 161 | "tmp/sharded_filter8_tiny.bin", 1); 162 | 163 | EXPECT_TRUE(source.contains(0x0000000000000000)); 164 | EXPECT_TRUE(source.contains(0x0000000000000001)); 165 | EXPECT_TRUE(source.contains(0x0000000000000002)); 166 | EXPECT_TRUE(source.contains(0x8000000000000000)); 167 | EXPECT_TRUE(source.contains(0x8000000000000001)); 168 | EXPECT_TRUE(source.contains(0x8000000000000002)); 169 | ``` 170 | 171 | The main classes are templated as follows to select underlying 8 or 16 172 | bit filters, giving a 1/256 and 1/65536 chance of a false positive 173 | respectively. The persistent versions are also templated by the 174 | `mio::mmap::access_mode` to select read or write (AKA source or sink): 175 | 176 | ```C++ 177 | namespace binfuse { 178 | 179 | template 180 | concept filter_type = std::same_as || std::same_as; 181 | 182 | 183 | template 184 | class filter; 185 | 186 | template 187 | class persistent_filter; 188 | 189 | 190 | template 191 | class sharded_filter; 192 | 193 | } // namespace binfuse 194 | ``` 195 | 196 | the following convenience aliases are provided: 197 | 198 | ```C++ 199 | namespace binfuse { 200 | 201 | // binfuse::filter 202 | 203 | using filter8 = filter; 204 | using filter16 = filter; 205 | 206 | using filter8_sink = persistent_filter; 207 | using filter8_source = persistent_filter; 208 | 209 | using filter16_sink = persistent_filter; 210 | using filter16_source = persistent_filter; 211 | 212 | // binfuse::sharded_filter 213 | 214 | using sharded_filter8_sink = sharded_filter; 215 | using sharded_filter8_source = sharded_filter; 216 | 217 | using sharded_filter16_sink = sharded_filter; 218 | using sharded_filter16_source = sharded_filter; 219 | 220 | } // namespace binfuse 221 | 222 | ``` 223 | 224 | ### Requirements and building 225 | 226 | POSIX systems and Windows(mingw) are supported, with a recent C++20 227 | compiler (eg gcc 13.2, clang 18.1), but it will also build with gcc-10.2 from 228 | Debian 11. 229 | 230 | ```bash 231 | git clone https://github.com/oschonrock/binfuse.git 232 | git submodule update --init --recursive 233 | 234 | cmake -S . -B build -DCMAKE_BUILD_TYPE=release 235 | cmake --build build 236 | ``` 237 | 238 | Tests are run automatically at the end of build. They can be disabled with `-DBINFUSE_TEST=OFF`. 239 | 240 | ### Including in your project 241 | 242 | The library, and its included upstream C-library are header only, but 243 | there is a `cmake` interface target available: 244 | 245 | ```cmake 246 | add_subdirectory(ext/binfuse) 247 | 248 | add_executable(my_exe main.cpp) 249 | target_link_libraries(my_exe PRIVATE binfuse) 250 | 251 | ``` 252 | 253 | 254 | ```c++ 255 | // main.cpp 256 | 257 | #include "binfuse/sharded_filter.hpp" 258 | #include "binfuse/filter.hpp" 259 | 260 | ... 261 | 262 | ``` 263 | 264 | ### A note on file formats and tags 265 | 266 | Two different binary formats are used for `filter` and 267 | `sharded_filter` 268 | ([details](https://github.com/oschonrock/binfuse/blob/192b4a0996565a9e5507577a7b67d26db0dcd532/include/binfuse/sharded_filter.hpp#L157)). They 269 | each have different build parameters, which further affect the 270 | structure. These are `fingerprint` size (8 or 16bit) and, in the case 271 | of the sharded filter, the number of `shards`. 272 | 273 | The file format parameters are recorded in the first 16 bytes of each 274 | file, so that files are not accidentally opened with the wrong 275 | parameters, giving bogus results. These tags are human readable and 276 | can be inspected with `hexdump`. 277 | 278 | ```bash 279 | $ hd filter8.bin | head -n1 280 | 00000000 73 62 69 6e 66 75 73 65 30 38 2d 30 30 36 34 00 |sbinfuse08-0064.| 281 | 282 | $ hd filter16.bin | head -n1 283 | 00000000 73 62 69 6e 66 75 73 65 31 36 2d 30 30 36 34 00 |sbinfuse16-0064.| 284 | ``` 285 | 286 | `binfuse` will throw exceptions, if files are opened with the wrong type/params. 287 | 288 | ### Benchmarks 289 | 290 | There is a benchmark for the `sharded_filter`, which includes figures 291 | for the `filter` internally. This can be built with 292 | `-DBINFUSE_BENCH=ON`. Some results below for 100m keys. 293 | 294 | It is difficult to run the `binfuse_bench_large` for 1billion or more 295 | keys, due to memory pressure, unless the first runs, with low shard 296 | count, are pruned out. This illustrates the precise motivation for the 297 | `sharded_filter`. 298 | 299 | Edit for your needs. 300 | 301 | ``` 302 | $ ./build/binfuse_bench_large 303 | 304 | Shard Size: 50000000 Shards: 2 Keys: 100000000 305 | 306 | gen populate verify add query f+ve 307 | f8 16.3ns 87.2ns 33.9ns 5.3ns 48.3ns 0.390792% 308 | f16 16.3ns 93.5ns 39.3ns 10.5ns 50.8ns 0.001542% 309 | 310 | 311 | Shard Size: 25000000 Shards: 4 Keys: 100000000 312 | 313 | gen populate verify add query f+ve 314 | f8 12.4ns 87.1ns 30.7ns 5.4ns 47.7ns 0.390143% 315 | f16 12.6ns 87.6ns 33.6ns 10.6ns 50.1ns 0.001487% 316 | 317 | 318 | Shard Size: 12500000 Shards: 8 Keys: 100000000 319 | 320 | gen populate verify add query f+ve 321 | f8 9.8ns 70.6ns 28.1ns 5.6ns 48.2ns 0.390789% 322 | f16 11.0ns 73.2ns 31.3ns 11.0ns 51.9ns 0.001483% 323 | 324 | 325 | Shard Size: 6250000 Shards: 16 Keys: 100000000 326 | 327 | gen populate verify add query f+ve 328 | f8 5.6ns 69.6ns 23.7ns 6.0ns 47.6ns 0.390566% 329 | f16 5.7ns 70.6ns 28.4ns 11.6ns 50.6ns 0.001511% 330 | 331 | 332 | Shard Size: 3125000 Shards: 32 Keys: 100000000 333 | 334 | gen populate verify add query f+ve 335 | f8 5.1ns 60.4ns 11.7ns 6.8ns 46.7ns 0.390106% 336 | f16 5.0ns 64.8ns 23.3ns 12.1ns 50.6ns 0.001576% 337 | 338 | 339 | Shard Size: 1562500 Shards: 64 Keys: 100000000 340 | 341 | gen populate verify add query f+ve 342 | f8 4.7ns 59.2ns 6.2ns 8.2ns 46.1ns 0.390199% 343 | f16 4.7ns 59.8ns 11.9ns 14.0ns 52.6ns 0.001496% 344 | 345 | 346 | Shard Size: 781250 Shards: 128 Keys: 100000000 347 | 348 | gen populate verify add query f+ve 349 | f8 4.7ns 56.6ns 6.2ns 10.2ns 46.4ns 0.390504% 350 | f16 4.7ns 54.6ns 6.4ns 17.1ns 48.4ns 0.001524% 351 | 352 | 353 | Shard Size: 390625 Shards: 256 Keys: 100000000 354 | 355 | gen populate verify add query f+ve 356 | f8 4.6ns 48.7ns 5.7ns 15.1ns 47.5ns 0.390732% 357 | f16 4.6ns 48.9ns 6.3ns 22.2ns 46.7ns 0.001484% 358 | ``` 359 | 360 | #### A note on memory consumption 361 | 362 | The first few runs of the above benchmark, with low shard count, will 363 | consume large, transient amounts of memory (1-2GB range) during 364 | `filter::populate`. The latter runs show the benefit of the 365 | `sharded_filter`, and the max memory consumption will settle at the 366 | size of the filter file (108MB/215MB for 8/16bit). 367 | 368 | **Note** that even this latter memory consumption is almost all in the 369 | `mmap`. The OS is likely deciding to just let your process cache the 370 | mmap fully in memory. This obviously benefits performance, but it is 371 | flexible disk cache. If the machine comes under memory pressure, these 372 | pages will be evicted. 373 | 374 | A huge dataset of 10 billion entries builds and queries just fine. The 375 | 8bit filter is 11GB and the 16bit filter is 22GB on disk. The stats 376 | below show how the 22GB, 16bit filter did not fit in the physical 377 | memory of the 16GB machine so the query time slowed to 0.7ms, but 378 | otherwise the system is quite stable. 379 | 380 | ``` 381 | Shard Size: 9765625 Shards: 1024 Keys: 10000000000 382 | 383 | gen populate verify add query f+ve 384 | f8 7.5ns 174.4ns 26.2ns 6.7ns 150.7ns 0.390653% 385 | f16 8.4ns 74.7ns 30.2ns 12.6ns 682612.8ns 0.001000% 386 | ``` 387 | -------------------------------------------------------------------------------- /test/data/sample.txt: -------------------------------------------------------------------------------- 1 | 000000005AD76BD5 2 | 00000000A8DAE422 3 | 00000000DD7F2A1C 4 | 00000001E225B908 5 | 00000006BAB7FC31 6 | 00000008C4037D3E 7 | 00000008CD1806EB 8 | 0000000A0E3B9F25 9 | 0000000A1D4B746F 10 | 0000000CAEF40543 11 | 01000000F6AFD75F 12 | 01000004386BCA31 13 | 0100000712F17F99 14 | 0100000A588E3E45 15 | 0100000CE9AF8CC7 16 | 0100000D1B0F43A8 17 | 0100000E4AD2C730 18 | 01000016BD485F5D 19 | 01000019DF85800B 20 | 0100001F8336CF60 21 | 0200001539D7FFDB 22 | 02000017BBED46AD 23 | 0200001F1C173EEA 24 | 0200002003055625 25 | 020000216755BC2E 26 | 0200002214DD88DF 27 | 0200002F0C429CC2 28 | 0200002F9CCD7B9A 29 | 020000376F18D091 30 | 0200003D5CDEF083 31 | 0300000151A35BE7 32 | 03000001F7166DB4 33 | 03000002B7E421DC 34 | 03000006F66A0DE8 35 | 03000019EF4139E8 36 | 03000021DC261F04 37 | 03000026077C25E5 38 | 030000263784A47A 39 | 0300002697D40EE6 40 | 0300002D19F9EC6F 41 | 04000000C2CCA19D 42 | 040000058EFD7B6B 43 | 04000005F4B20D2C 44 | 0400000713BB3BDD 45 | 0400000BEF909F0C 46 | 0400000C9A8FB171 47 | 0400000DFE2419C2 48 | 04000015D2BC4994 49 | 0400001632D1B4E0 50 | 04000016F4A2ECED 51 | 050000001F7F5D2A 52 | 05000002D0DFC3EB 53 | 050000080FA35948 54 | 0500000B03E6D718 55 | 0500000CB7BE5FEF 56 | 0500000D171A03F5 57 | 0500000D2F8E728D 58 | 0500000E9358AC48 59 | 0500000FF6E44A82 60 | 050000180530F30F 61 | 06000003C0378817 62 | 060000054EDFDFE3 63 | 0600000861FAE6BC 64 | 0600000F83464EE1 65 | 06000016A8EDF593 66 | 06000017C31DB216 67 | 06000020BBA9D9B4 68 | 0600002135F8E7A7 69 | 060000222F8E7AA6 70 | 060000263D3193E9 71 | 070000038ED0C40C 72 | 070000047F35C0F6 73 | 07000004FDB5DE63 74 | 070000056DDDF0FB 75 | 07000007A225684B 76 | 070000081F8A3DA8 77 | 0700000956F13333 78 | 0700000F7A21C7DA 79 | 0700000FFF30AEDF 80 | 07000013E1F4BD36 81 | 08000004CBD496A9 82 | 080000056310722A 83 | 080000071B3802A7 84 | 0800000BC37FE086 85 | 0800000CF66B655C 86 | 0800000D9D06CDD9 87 | 080000106504E059 88 | 080000135964DB3D 89 | 0800001464A952E3 90 | 08000016CF1DC10C 91 | 0900000234D45691 92 | 0900000B47AB3634 93 | 0900000BD0CAECE3 94 | 0900000C021A2172 95 | 0900000E363EFAA1 96 | 0900001DB287BA23 97 | 0900002A8D563F4D 98 | 0900002F719F097B 99 | 09000031CFD429F4 100 | 0900003BD4CC1063 101 | 0A000000469582D2 102 | 0A000003865E8FEA 103 | 0A000007835E28EB 104 | 0A000009466BDC04 105 | 0A00000A3F4A058E 106 | 0A00000B48BAEDE4 107 | 0A00000B674AF8BB 108 | 0A00000B7E3F4752 109 | 0A00000DE922B69D 110 | 0A00000DF0B939CA 111 | 0B00000230E130AC 112 | 0B000002A1715A63 113 | 0B00000AE4296E47 114 | 0B00000B12F325FB 115 | 0B00000E490BB582 116 | 0B000010ADA1ED81 117 | 0B0000117A40D753 118 | 0B0000171327F282 119 | 0B00001860C75481 120 | 0B00001C41F8D781 121 | 0C0000023AE4FA23 122 | 0C00000356216B7C 123 | 0C000003EEE5F8EA 124 | 0C0000083C5B586F 125 | 0C00000AF339A755 126 | 0C00000EDC3EC262 127 | 0C00000FBF8E7D4B 128 | 0C00001047BA108E 129 | 0C000010B48070E9 130 | 0C000012B69A09CD 131 | 0D00000839F3B75E 132 | 0D00000A43B46AAE 133 | 0D00000C49786B1F 134 | 0D00000D2E816A33 135 | 0D00000F04DAC27F 136 | 0D000012856C8ADC 137 | 0D000018B8C55CFF 138 | 0D000021F4935C93 139 | 0D00002305279732 140 | 0D0000252C1F5B64 141 | 0E000000295814F4 142 | 0E0000027A442819 143 | 0E00000554E36807 144 | 0E0000058ECC3D8B 145 | 0E00000684006C75 146 | 0E00000834D53C3E 147 | 0E00000CB0CFE565 148 | 0E000010B5475608 149 | 0E0000121FD41BBB 150 | 0E00001282DDC433 151 | 0F0000003121926B 152 | 0F0000077A717BB9 153 | 0F00000A02EF4FC4 154 | 0F00000BDB5ADA11 155 | 0F00000BF89A19AE 156 | 0F000013952AAD04 157 | 0F000018731B7A22 158 | 0F00001E71AE5E25 159 | 0F0000208A4AD78F 160 | 0F000020E5B91271 161 | 100000006C1AE53C 162 | 10000001D2C1EBCD 163 | 10000002E9D27720 164 | 100000086A0229A9 165 | 1000000D6B06FDB3 166 | 1000000FB3B9409F 167 | 1000000FF54609F3 168 | 100000117391403F 169 | 1000001D0E58DDCA 170 | 100000249AE0F60D 171 | 11000001F5B441A1 172 | 1100000235F5778C 173 | 11000003DFE0DCB2 174 | 11000004D4F2B634 175 | 11000005FEF5E8DD 176 | 1100000D10D03BB9 177 | 1100000FC8C52EDE 178 | 1100001AC8CDC132 179 | 11000022B30B8C15 180 | 11000023859A2336 181 | 12000000BDB3AB5D 182 | 120000011E000E03 183 | 120000060B3BBFB4 184 | 12000009D428D5F2 185 | 1200001F1B9B79DB 186 | 1200002E1F666C07 187 | 1200002F4AD5FFD6 188 | 12000038655A8F56 189 | 12000041526D744A 190 | 12000041EADF2DAD 191 | 13000003626D90E5 192 | 130000136A88B589 193 | 13000013E4E3C7F2 194 | 1300001603A85605 195 | 1300001B552866A0 196 | 1300002871B3E36F 197 | 13000028FE684D1D 198 | 13000029579C4A62 199 | 13000029E280C71A 200 | 13000029FD4D9A8C 201 | 140000000943037C 202 | 1400000196A7001E 203 | 14000001F2CBCD62 204 | 1400000607BABB77 205 | 1400000766370243 206 | 14000018DFC88B56 207 | 14000023A6525DB5 208 | 14000024A13BB6F2 209 | 1400003145C62FCB 210 | 14000031EE0379FE 211 | 15000005FDED62AC 212 | 150000135B9CB84B 213 | 150000137420284B 214 | 1500001376BE6373 215 | 1500001761775210 216 | 1500001793F12617 217 | 1500001FEC73DBB4 218 | 15000021B9647200 219 | 1500002414D3BCD7 220 | 15000026E78873ED 221 | 160000071416103D 222 | 1600000EC75AE7FB 223 | 16000012C16E0FD4 224 | 160000140911E564 225 | 1600001F8E635672 226 | 1600001FD23883E0 227 | 16000020B4F0ED9A 228 | 16000021BF60212E 229 | 1600002BC58FE257 230 | 1600002D198E9F66 231 | 17000002D2833529 232 | 17000004F339CA07 233 | 1700000579886808 234 | 17000014E9AEC5E8 235 | 170000212DC76124 236 | 17000022ED9A2642 237 | 17000023B692BE88 238 | 1700003E2FF0C0BD 239 | 1700003EAFBE332F 240 | 17000041137740AE 241 | 18000000E516DCC4 242 | 1800000325ABBB03 243 | 180000170108E478 244 | 1800001816127A58 245 | 1800001A93FE3E81 246 | 18000020E7E743F0 247 | 180000253DA0829B 248 | 180000269A407BBB 249 | 1800003696EAF677 250 | 18000036C1796E6E 251 | 19000001B1C816B2 252 | 19000007586C48A0 253 | 190000081D837753 254 | 1900000A38DA8519 255 | 190000143CD7B4D5 256 | 19000019C543BC69 257 | 19000037277DF424 258 | 1900003ABF83733A 259 | 1900003C82663C92 260 | 1900003EB204AAF2 261 | 1A0000009F742CC1 262 | 1A000001E1C6A28F 263 | 1A000002312B2116 264 | 1A0000026D661166 265 | 1A000010B5EC82D5 266 | 1A000010EF80DBE5 267 | 1A000016475AC7CD 268 | 1A00001AF88D616C 269 | 1A00001D4DA0653C 270 | 1A00002145DE4869 271 | 1B00000011DE3F1B 272 | 1B00000309DD4C64 273 | 1B000005E2BA1F21 274 | 1B0000072EF2E52F 275 | 1B00000D3289ED15 276 | 1B00000FAA7B3728 277 | 1B000010360ED111 278 | 1B000012EAD7852C 279 | 1B000013EB00F054 280 | 1B000017696E5670 281 | 1C000000432F9557 282 | 1C0000052D6F145B 283 | 1C000005C4E97D9A 284 | 1C00000B66B97374 285 | 1C00000D6027CEFA 286 | 1C0000181B649E7C 287 | 1C000020BCAF2068 288 | 1C0000225D1646C2 289 | 1C000023CDFE0264 290 | 1C00002B5195E4F7 291 | 1D000004C4D9395D 292 | 1D0000075E826E4B 293 | 1D00000AA5399419 294 | 1D00000B00CECE12 295 | 1D00000C6C15E21C 296 | 1D000015A282EC45 297 | 1D00001AEFC01C54 298 | 1D000023CFB132A6 299 | 1D00002D2E6917F8 300 | 1D00003C5DC6E8F6 301 | 1E00000268C88665 302 | 1E000005EDACD8BF 303 | 1E000009BD0E03BA 304 | 1E00001330E74CF6 305 | 1E0000135B1D3A2C 306 | 1E000015E351B275 307 | 1E0000200D41310F 308 | 1E00002BD5C2A231 309 | 1E00002C470017E8 310 | 1E00002C9AC1FCBF 311 | 1F00000319D5BE65 312 | 1F000004DDFA02DF 313 | 1F00000E2E854A02 314 | 1F00000E31CB7BF9 315 | 1F00001A0CDFACEC 316 | 1F00001B37721A9C 317 | 1F00001E1365C772 318 | 1F0000241D3B0D62 319 | 1F00002AF71888C4 320 | 1F000031075D8A5D 321 | 200000000AD1EBEA 322 | 20000000DBD1DC76 323 | 20000003B32C7ED0 324 | 20000004B8A9F3E5 325 | 200000090B709D2D 326 | 2000000996BA5AF8 327 | 2000000BD59649EC 328 | 200000131452DDB5 329 | 200000178FA007DD 330 | 20000019B94FA367 331 | 2100000033F092C6 332 | 210000058F65A9F3 333 | 2100000763D727D5 334 | 21000009322495D5 335 | 2100000B8962D819 336 | 21000010D2EB0E80 337 | 2100001B64849FE7 338 | 2100001C306B4B3D 339 | 210000206B200712 340 | 21000022C947299F 341 | 22000000781DED99 342 | 220000011FA34F11 343 | 220000017D9D961A 344 | 22000001BDB0E411 345 | 220000043FFF9BB5 346 | 2200000BAC95A4D1 347 | 2200000E013FEB0D 348 | 2200000F7C0A23FE 349 | 2200001761EF44CF 350 | 2200001E260718FE 351 | 230000067C771311 352 | 230000070EA18C36 353 | 2300000C24E03CB9 354 | 2300000D610CBBF3 355 | 23000010264603B2 356 | 230000121124E6DE 357 | 2300001362ED311F 358 | 23000017CD846E78 359 | 23000018CD833CC2 360 | 230000196E9504DE 361 | 24000002114AFB30 362 | 240000082A78209B 363 | 24000010794D26EF 364 | 2400001296688628 365 | 240000157F763198 366 | 24000015FB246DA7 367 | 24000019A1484026 368 | 24000019B7AF0ACC 369 | 240000258294E66E 370 | 24000029B9BB3C14 371 | 25000000F959A6D8 372 | 25000002883AF84F 373 | 2500000766BCEE41 374 | 25000007EBED6074 375 | 25000008C90B37F8 376 | 2500000945E9215D 377 | 25000009528ADEA7 378 | 25000014399418E1 379 | 2500001548F4ECE6 380 | 25000018BAB5C2E5 381 | 2600000111E94686 382 | 2600000B351C1957 383 | 2600000E49EBA12B 384 | 2600000F7BFE3D6A 385 | 2600002004F7C3F6 386 | 2600002539D95638 387 | 26000027C45056DA 388 | 2600002A506502B3 389 | 2600002B44BD2474 390 | 26000037D5454BF2 391 | 27000003B299969D 392 | 27000004350B04E5 393 | 2700000D99DFEE5A 394 | 2700000E07210C35 395 | 2700000E35492E59 396 | 27000012875575C3 397 | 27000019089FC717 398 | 2700001C9751078D 399 | 2700002053A4DB03 400 | 27000023CFA68885 401 | 280000034F41B3C6 402 | 2800000393E00B63 403 | 2800000D62391672 404 | 2800000EDB21AAB3 405 | 28000013D898CA16 406 | 28000019A7E589F4 407 | 2800001C4209D483 408 | 2800001D391CE117 409 | 280000211EA89DB5 410 | 280000312C092B00 411 | 2900000511609492 412 | 29000005F9C42057 413 | 2900000645277DE4 414 | 29000006EFE56CD8 415 | 2900000AC8944372 416 | 2900000CA0AFAFCE 417 | 2900000FFEA7D003 418 | 2900001D43375004 419 | 290000245D838F88 420 | 29000026615F74EA 421 | 2A0000009984E85C 422 | 2A000002965F6929 423 | 2A0000053BD57281 424 | 2A00000B285057DD 425 | 2A0000100C59EB1C 426 | 2A000011FD64E76C 427 | 2A0000130CE3FF17 428 | 2A0000132D5031C9 429 | 2A0000135EE29A5F 430 | 2A000015B4A4DC42 431 | 2B000000D7F1527E 432 | 2B000002D74567D2 433 | 2B00000811B98097 434 | 2B00000B280A889C 435 | 2B00000D43497CCD 436 | 2B00001610BE198C 437 | 2B000016586342D3 438 | 2B0000207A14169B 439 | 2B0000232FFE5456 440 | 2B000023D3BB0666 441 | 2C0000004AB744DB 442 | 2C00000120119898 443 | 2C0000042F01496A 444 | 2C000007351D11FC 445 | 2C00000E31975D7C 446 | 2C0000143244A615 447 | 2C0000173D700E6D 448 | 2C000018FD2C4A03 449 | 2C00001A273E36CA 450 | 2C00001BCAE4142B 451 | 2D000001388D9657 452 | 2D00000255BC0A02 453 | 2D00000806BD4EC8 454 | 2D0000093477B0F6 455 | 2D000009DC63CC8E 456 | 2D00000A39201051 457 | 2D00000D28531A14 458 | 2D00000F35DAF82B 459 | 2D000011D09B0BCF 460 | 2D00002532969B33 461 | 2E0000023DBFE8EF 462 | 2E00000298BCD757 463 | 2E000007BFA2A069 464 | 2E00000EB7D8F89B 465 | 2E00000EC6B6F92B 466 | 2E00001326BA0930 467 | 2E000015D41CEF00 468 | 2E000017F30207F6 469 | 2E00001945402452 470 | 2E00001CF9C1FAD7 471 | 2F00000184343C73 472 | 2F000002EDD281B5 473 | 2F00000CA963EC99 474 | 2F00000D88AB67CF 475 | 2F00000FE36AAC1C 476 | 2F00001470DD974C 477 | 2F00001914B30719 478 | 2F00001DA3114236 479 | 2F000026239AEE32 480 | 2F000033CF989D8C 481 | 3000000205751731 482 | 300000047D3854BB 483 | 3000000C041FD774 484 | 3000000D4737E40C 485 | 3000001273009FCC 486 | 30000013C0C92652 487 | 30000018B9A4C575 488 | 3000001BDCC0F12A 489 | 3000001D0875F77A 490 | 30000021791260B1 491 | 3100000003E50507 492 | 310000016D971E44 493 | 31000003608A949C 494 | 3100000622B6E21A 495 | 31000012B3FB6230 496 | 3100001C86846716 497 | 3100001F8CA45F3D 498 | 3100002032C01F01 499 | 310000204910EA54 500 | 31000023F2F5B5B9 501 | 320000006ED3B5D1 502 | 32000008EF1A68E4 503 | 3200001038C83511 504 | 320000106FB431AB 505 | 320000123952FBE1 506 | 32000015B96EE219 507 | 32000017687A3496 508 | 3200001C849FA71A 509 | 32000022CAA142FD 510 | 32000026AF96B14D 511 | 330000024CDA8A61 512 | 330000051E1C9DAE 513 | 3300000A87DD6884 514 | 3300001DCCB8F64B 515 | 3300001EBA98C426 516 | 330000225B4769DD 517 | 33000024F020D2C9 518 | 3300002595AEBD09 519 | 3300002BE71DEA09 520 | 3300002D6E455587 521 | 34000000369A931B 522 | 3400000406B0EEE4 523 | 34000010EEDAFB0B 524 | 34000014104BBD83 525 | 34000019D5340589 526 | 3400001CD75D62DA 527 | 34000021FF4D2179 528 | 34000023C0ACAC1B 529 | 340000245186A567 530 | 340000282E2EFAC6 531 | 35000004C35FAEEC 532 | 3500001E388CDECB 533 | 35000023D613E877 534 | 35000024FCEA813A 535 | 350000261980AB6A 536 | 3500002AF8B41AF2 537 | 35000037E451C74A 538 | 3500003C77636369 539 | 3500003F996E8428 540 | 3500004108B02803 541 | 36000006AEFD27C6 542 | 3600000781E81953 543 | 3600000AD2BAD4E3 544 | 3600000CD3B4F21C 545 | 3600000ECCAF05F6 546 | 360000101C7FF7D9 547 | 36000011BAF676E4 548 | 3600001B6EA5A18E 549 | 36000021A382CE2D 550 | 3600002BD2719CBD 551 | 37000003AAF371AE 552 | 370000042F614935 553 | 3700000AFF3AB9A0 554 | 3700000F8721D789 555 | 37000015189E5F97 556 | 370000160589F123 557 | 370000172C4049AF 558 | 3700001ABD9D0C9C 559 | 3700001B17C765AA 560 | 3700001E65F294C5 561 | 380000001DDA2AF8 562 | 380000031857A43A 563 | 380000112B66DB5F 564 | 3800001BAAD9C2A5 565 | 3800001E6F377145 566 | 38000022F227E936 567 | 38000023B59C0C0F 568 | 38000035FCF3FD84 569 | 3800003691015B08 570 | 3800003AE8C2616A 571 | 39000002B61D6C49 572 | 390000078BF78BEF 573 | 3900000A8997C85E 574 | 3900000C2EFE9C4B 575 | 3900000E98D3C501 576 | 3900000F5AC62719 577 | 39000012A4BBAD3E 578 | 39000019068C1901 579 | 3900001E06C5CE40 580 | 3900001E6E7A8CC9 581 | 3A00000BACC295CA 582 | 3A0000127B5801B8 583 | 3A000013E8C4AE01 584 | 3A00001EA84A1B95 585 | 3A00001EB2C05D36 586 | 3A0000250B8B82E7 587 | 3A0000260FC751C9 588 | 3A000027A4975579 589 | 3A00002ADDED205D 590 | 3A00002EBE92E7B9 591 | 3B000000803969B6 592 | 3B000005D9B5AABC 593 | 3B00000A79E8DA64 594 | 3B00000D94749E30 595 | 3B00001014927D2E 596 | 3B00001C02734562 597 | 3B00001C971EBB10 598 | 3B00001E78609F6C 599 | 3B00002034D07E89 600 | 3B000022B8F1FB8E 601 | 3C000004041D2A28 602 | 3C000009BEE505C6 603 | 3C00000A773B9D65 604 | 3C00000B714FAFCD 605 | 3C00000D912EC9B8 606 | 3C0000238C41FDFA 607 | 3C000027BE8A2A4D 608 | 3C000028102EB359 609 | 3C00002955324450 610 | 3C000031953319EF 611 | 3D000003424376BC 612 | 3D000004B371AE76 613 | 3D000007F9381D83 614 | 3D00000D2C727509 615 | 3D00000F0DD65CD2 616 | 3D000012A5229F06 617 | 3D000015CA45DE7E 618 | 3D00001F0A432C8C 619 | 3D000022F146F9AA 620 | 3D00002374194AF9 621 | 3E000000182F38DE 622 | 3E000005354FAA60 623 | 3E0000066BC7746F 624 | 3E0000089473BD37 625 | 3E0000101ACEB368 626 | 3E0000178B5F3304 627 | 3E00002646CF4D11 628 | 3E000026F02DF4FB 629 | 3E000034F8747D9C 630 | 3E000035E9374D92 631 | 3F00000675B49569 632 | 3F00000688BC9F83 633 | 3F00000F4618C324 634 | 3F000011E8DF85A2 635 | 3F000011F79AC496 636 | 3F0000135E3CEE23 637 | 3F000013A0ECB000 638 | 3F00003261393AD9 639 | 3F000034F8EDA015 640 | 3F00003CEA3F2F87 641 | 40000000D61EF012 642 | 4000000216D74843 643 | 400000099D5574E2 644 | 4000000FDCF6FDFB 645 | 40000010BCA92F28 646 | 4000001E0F11E91C 647 | 400000249AFDFF90 648 | 4000002C3545EB5E 649 | 40000035C8BE9ECA 650 | 400000371A9E23B9 651 | 410000011029B21A 652 | 410000022E2A81AB 653 | 41000004DC990762 654 | 4100001FBC490BA1 655 | 41000022DCCA8AED 656 | 4100002582218A87 657 | 41000027448066B3 658 | 4100002D95C1E400 659 | 4100003AF2E4F967 660 | 4100004064E8FE08 661 | 4200000935F7AD57 662 | 4200000D4D76E60B 663 | 42000013DE0FEFF8 664 | 42000017368C2770 665 | 42000019083DFE25 666 | 4200001AAE4601AB 667 | 4200001BBF5FECBE 668 | 4200001FFEB98C17 669 | 42000021D1AEA4D5 670 | 4200002237C96FE8 671 | 4300000065A00BF6 672 | 43000003D45628AC 673 | 43000004801CB8BB 674 | 43000006DD227140 675 | 4300000963E6A23D 676 | 430000099D23AA8B 677 | 430000108A16BC97 678 | 43000010EE3D11C2 679 | 430000141451D5F7 680 | 430000153AC729DA 681 | 44000008BC34E39E 682 | 4400000BBEEBC538 683 | 4400000CC1AB2298 684 | 44000013E47654ED 685 | 44000014F7C1593B 686 | 4400001B59B9F7CD 687 | 44000024DCA4388B 688 | 44000028EE722DD2 689 | 4400002961B2AE93 690 | 4400002A753FCEE6 691 | 45000005A8B03E80 692 | 450000076806C237 693 | 4500000B43ACE35E 694 | 4500000E47972035 695 | 4500000FA72133AB 696 | 4500001164484387 697 | 450000127C118C13 698 | 45000012BA2CDB99 699 | 4500001928ECA2BD 700 | 4500001E966FB458 701 | 46000003F9BCB314 702 | 46000009C7503D69 703 | 4600000F9BCF9CD7 704 | 46000017983CABB9 705 | 460000188BB02FB1 706 | 4600001C0A9B46F4 707 | 460000289AC58F3F 708 | 4600002D948774A5 709 | 4600003089CD14EE 710 | 460000401A412370 711 | 47000003924365CA 712 | 47000004E7FDE4B9 713 | 4700000DC5E6EE4D 714 | 4700000F00E554AF 715 | 4700000FE90DB77B 716 | 470000117F7508E7 717 | 4700001943B007A6 718 | 4700001AD2AC4B00 719 | 4700001DB4482D84 720 | 4700001E11DF6F43 721 | 4800000B051547FA 722 | 4800001195454903 723 | 48000012A0D75913 724 | 4800001435DE75AF 725 | 48000014B1861E0C 726 | 48000014BE93AEA4 727 | 480000198FE91BCA 728 | 48000019C4D1B6A0 729 | 480000242348521C 730 | 48000024DD0B8F17 731 | 49000003FCFF27B0 732 | 49000005473CBB41 733 | 490000057B10C7C6 734 | 4900000DB89DDFD1 735 | 490000119D569F86 736 | 490000132ED7000B 737 | 49000016B66127CB 738 | 4900001F30BE18CF 739 | 4900001F86AC1F18 740 | 4900002033C8987B 741 | 4A0000004BC3FD7A 742 | 4A000005FCF26941 743 | 4A000008018C79A8 744 | 4A00000B64B6353B 745 | 4A0000145863989D 746 | 4A000017CFACDBDE 747 | 4A000019B0D3E547 748 | 4A00001C0AB33B41 749 | 4A00001C5B853EF2 750 | 4A000021AA23AAB9 751 | 4B0000015CC37517 752 | 4B00000ADD46CD1A 753 | 4B00000CF9950021 754 | 4B00000DCBA5E3BF 755 | 4B00000EBF11D775 756 | 4B000011A0B84DB9 757 | 4B00001E3A1C779F 758 | 4B000026C1BD6756 759 | 4B0000273000E794 760 | 4B00002773A9E428 761 | 4C00000189E140D2 762 | 4C000001A80326DB 763 | 4C00000641C26586 764 | 4C00000719AA6E41 765 | 4C00000F12114F1E 766 | 4C00001157A7D244 767 | 4C0000185532FFA3 768 | 4C00001CD21FBCA1 769 | 4C00001D17DD5B28 770 | 4C00002B1A180B7F 771 | 4D000002DACA82B3 772 | 4D000014ADE12030 773 | 4D00002193057BB2 774 | 4D00002B4CF33F19 775 | 4D00002E92D204F2 776 | 4D000031928A92C0 777 | 4D000044036A3704 778 | 4D0000445C723A75 779 | 4D0000462E94BB32 780 | 4D00005B005A04ED 781 | 4E00000002093149 782 | 4E00000A2D349CB9 783 | 4E00000BFCC771A1 784 | 4E00000E208F9C26 785 | 4E000010A5B5C9D9 786 | 4E00001277CB2935 787 | 4E000014751C8A8E 788 | 4E0000177E93EDBE 789 | 4E00001A1E661A70 790 | 4E00001AB4E6FD98 791 | 4F000002B0D03DBB 792 | 4F00000A2456650E 793 | 4F00000D4B02FA32 794 | 4F00000FC31868E3 795 | 4F0000115F32869F 796 | 4F0000135D2170C5 797 | 4F0000138DB0016B 798 | 4F000017EBF6D2C9 799 | 4F00001B72E2ACEC 800 | 4F00001DC3FCE0D6 801 | 500000007CE9839D 802 | 50000003498A55CB 803 | 5000000AF5ECB195 804 | 5000000CCB8BC9CC 805 | 5000000EC9171C0C 806 | 5000000FBBC92ECB 807 | 50000010D90C52A7 808 | 50000019C96C8F94 809 | 5000001AE85267EA 810 | 5000001C37C6749A 811 | 5100000A8E70B8F9 812 | 5100000F2206470A 813 | 510000162C5C9E4E 814 | 51000019D0460868 815 | 5100001D8158DAB1 816 | 5100001E80976DCD 817 | 5100001ED30A0FFA 818 | 51000024B100418C 819 | 51000027691C39A6 820 | 51000028E520BE75 821 | 52000000A6DE5B24 822 | 52000005AF4CAA4A 823 | 5200000DFDEFA1DD 824 | 5200000E582D2B9A 825 | 5200001269EE045F 826 | 520000157C533457 827 | 52000019C63C0D11 828 | 5200001C5FED2038 829 | 5200001E0318E933 830 | 5200001F3C4AED9A 831 | 5300000541E0475A 832 | 53000005690A786D 833 | 5300000625A42796 834 | 53000008808DE040 835 | 5300000EB6878EA3 836 | 53000011B4747BDD 837 | 530000175E5710A9 838 | 53000017CF828E92 839 | 5300002877540227 840 | 5300002B9CFC5B2C 841 | 54000000282C86C1 842 | 540000023EF70483 843 | 5400000734F1ADB7 844 | 5400000E30625BFF 845 | 5400000E86881516 846 | 5400000F666FF304 847 | 540000147D652EE1 848 | 54000018889B610D 849 | 54000020142BC1B0 850 | 540000224D7645DC 851 | 55000009894EC8F6 852 | 5500000BB1DDBBC3 853 | 5500001432888B73 854 | 5500001AD65DCFBD 855 | 5500001B2F6AE301 856 | 550000218A0B1FA5 857 | 5500002EBD01BBD7 858 | 5500002FE7D6E66A 859 | 550000408A277BC4 860 | 5500004B6C079EC9 861 | 560000005684995D 862 | 5600000DB1D55B77 863 | 5600000E97AB6B24 864 | 5600001661E05082 865 | 56000018D77DF33A 866 | 5600002A162D3B61 867 | 56000043DCFAE931 868 | 5600004861F96265 869 | 56000048C03DA4E3 870 | 5600005679EC45B5 871 | 57000004DFF2C78C 872 | 57000013E86228BC 873 | 5700002859CCBD29 874 | 5700002C4CCFB8AB 875 | 5700002D851A07EF 876 | 570000365785C001 877 | 57000037BCFAA238 878 | 5700003E6F870D49 879 | 5700003F58036815 880 | 5700004EE4D8C74F 881 | 5800000588B36F11 882 | 580000094592BF13 883 | 5800001229A8748F 884 | 58000014ED87D2AC 885 | 58000016E9BF256A 886 | 58000019144AF165 887 | 58000022EF4879DC 888 | 58000024AA37474A 889 | 5800002694834FD8 890 | 58000028FBE460A0 891 | 590000058C4FD403 892 | 5900000873D59AFC 893 | 59000008FF40784A 894 | 5900000CEA5CAA37 895 | 5900001605025D81 896 | 59000016F73CC748 897 | 5900001A6050848E 898 | 5900001CE2A66FCF 899 | 5900001E37DDA88C 900 | 590000215DB144B7 901 | 5A00000710AEDDAC 902 | 5A00000A6E3263FE 903 | 5A00001221528E13 904 | 5A000023C2604461 905 | 5A000029644AAFF0 906 | 5A00002BF6656A05 907 | 5A00002C0F5CAC1F 908 | 5A000030392FD049 909 | 5A000032C7D29D56 910 | 5A000032EF0E6C2C 911 | 5B0000041BFEAFBA 912 | 5B00000B626CA974 913 | 5B00000DD5FD97F0 914 | 5B00000E2376FC57 915 | 5B00001155C55395 916 | 5B000012A2A1DF6C 917 | 5B00001AB0523A79 918 | 5B00002A7BFF1E6D 919 | 5B00002AADEEF85F 920 | 5B00002C0E7DA7F3 921 | 5C000000F25E8782 922 | 5C0000057362C365 923 | 5C00000AB771DE8D 924 | 5C00000BC4C5B0C7 925 | 5C00000BEA4952F5 926 | 5C00000DAD7C0274 927 | 5C0000117EB44F3F 928 | 5C00001249019FE8 929 | 5C000016F5071821 930 | 5C00002376F81831 931 | 5D0000002B94570B 932 | 5D000000DD535B76 933 | 5D00000B26C54D90 934 | 5D00001DAF2126CD 935 | 5D000028ADA9F2B7 936 | 5D00002B0316D3E1 937 | 5D00003253AA3253 938 | 5D000046E40E5DC0 939 | 5D000050ECC74FCB 940 | 5D0000511B3419B7 941 | 5E0000004B95820E 942 | 5E00000300CD91D9 943 | 5E00000368A4B459 944 | 5E00000556AAA9EA 945 | 5E0000086CAC5B18 946 | 5E00000D26AA9C0F 947 | 5E00000D3A48C5B5 948 | 5E00000D4EA1325F 949 | 5E000013DFB01269 950 | 5E000015962FBFAB 951 | 5F00000BC1FB074B 952 | 5F00001198DC0F65 953 | 5F00001216C61FC6 954 | 5F00002102C34934 955 | 5F0000239CBC5100 956 | 5F000023FA24D711 957 | 5F000033ACFA60C1 958 | 5F0000392AFD82D5 959 | 5F00003954398A77 960 | 5F000044CDC78321 961 | 60000000FB3EC38F 962 | 60000006084083EA 963 | 600000065DD96E53 964 | 6000000B51CB37AD 965 | 6000000E3FF787F5 966 | 6000000FBA311B94 967 | 600000115918A888 968 | 600000155CB677E5 969 | 60000016F451B4EC 970 | 6000001A91BCE374 971 | 61000008B0769CD2 972 | 6100000B5F671A7D 973 | 6100000D9B17A72E 974 | 6100001323EF1278 975 | 61000016F36C7B4B 976 | 6100001749CF101F 977 | 6100001F9574F075 978 | 6100001FE8D45E62 979 | 610000205BC04C3B 980 | 610000257363D4E4 981 | 62000007572E8B1D 982 | 6200000774D4EE1F 983 | 62000009A564F070 984 | 62000009AEF881B7 985 | 6200000F939EC164 986 | 62000018CD3B28B4 987 | 6200001BA55413ED 988 | 6200001C9A52B974 989 | 6200001F42A6315E 990 | 62000021DCAF4CF1 991 | 63000000BAD75356 992 | 6300000264A3D5F5 993 | 6300000340A1B7CC 994 | 63000006BCFDD09E 995 | 6300000AA15CFB81 996 | 63000010D9DF7BE9 997 | 63000017A6CD07A5 998 | 6300001942DA3C28 999 | 6300001B56F1D26B 1000 | 6300001CB64E5326 1001 | 640000021AFC0833 1002 | 640000062BB3BBDF 1003 | 6400000C0DE7094E 1004 | 6400000C1A09144F 1005 | 6400001457EBA0E9 1006 | 64000017C1DE82EA 1007 | 64000021D163DC87 1008 | 640000221224C249 1009 | 640000266E128CBC 1010 | 6400002906C4522E 1011 | 650000019D730D06 1012 | 65000009A6D05953 1013 | 65000009FBA32FBB 1014 | 6500000B6E28650C 1015 | 6500000B9252C760 1016 | 6500001126577237 1017 | 6500001594417886 1018 | 65000016CBF2E704 1019 | 6500001D1E41339A 1020 | 650000280956E5FE 1021 | 66000003D5EBD2A3 1022 | 660000078F94478E 1023 | 6600000A3FBCA138 1024 | 6600000B5B99BB54 1025 | 660000139EC5F201 1026 | 6600001975E83F8A 1027 | 6600001C1F5AC717 1028 | 6600001C610D9FC7 1029 | 660000218900C6B8 1030 | 660000236272200A 1031 | 6700000156579B40 1032 | 67000002EE10022B 1033 | 670000096B434E6E 1034 | 6700000A5DE973B7 1035 | 670000147A5624ED 1036 | 67000014D78265B1 1037 | 67000016BE2E42E6 1038 | 6700001AB2555956 1039 | 67000028794541E4 1040 | 670000371305AFAC 1041 | 6800000320B66354 1042 | 68000009CFDB0BA5 1043 | 6800000B56072891 1044 | 6800000B8569B5A2 1045 | 6800000BF677266A 1046 | 6800000EFDCB4D47 1047 | 680000100E6ADED9 1048 | 6800001027C95B6D 1049 | 6800001343C4A111 1050 | 68000019AA838CB0 1051 | 69000002DA5F02C4 1052 | 6900000444D434EA 1053 | 690000052A50CB5C 1054 | 69000005447AD302 1055 | 690000118B2D1434 1056 | 69000011FA0C8776 1057 | 690000176676AC2B 1058 | 6900001872C63549 1059 | 690000224637A882 1060 | 69000023125C273F 1061 | 6A0000024326FD6B 1062 | 6A000002E9A8130E 1063 | 6A0000047F5D09CE 1064 | 6A000008D45B4ECE 1065 | 6A00000B6BC89A57 1066 | 6A00000E67E0E81F 1067 | 6A000010CE826506 1068 | 6A000012499A3C2E 1069 | 6A000021E1525C8C 1070 | 6A00002E6F45EE1F 1071 | 6B000003AB7AE187 1072 | 6B000004248C17A9 1073 | 6B00000BD9668D60 1074 | 6B00000F1D52A284 1075 | 6B00001022C795DB 1076 | 6B000011E91860DC 1077 | 6B000013E0189BC4 1078 | 6B00001B376ADF1B 1079 | 6B00001FABADC48F 1080 | 6B000026D8EF4309 1081 | 6C00000035FD243C 1082 | 6C000004A1C4DA9C 1083 | 6C00000688E5C365 1084 | 6C0000088FF3C0EE 1085 | 6C00000EAAF6F357 1086 | 6C000016003EE4B6 1087 | 6C00001E78D3B5F2 1088 | 6C00002141802F91 1089 | 6C000022CBFB3BFC 1090 | 6C00002322421CFA 1091 | 6D000003058C45C5 1092 | 6D000005128EFB81 1093 | 6D0000051EAFD460 1094 | 6D0000056F6EAA53 1095 | 6D00000894A7DD48 1096 | 6D000008C305AB64 1097 | 6D00000BCDDB1C94 1098 | 6D00000DD5177B01 1099 | 6D000015BE03EE51 1100 | 6D000019C4888190 1101 | 6E00000467C7BAFB 1102 | 6E00000FB9372C8D 1103 | 6E000019BD623D17 1104 | 6E00001FEACC56B6 1105 | 6E000020EEFDA28C 1106 | 6E000021D03A39E6 1107 | 6E000022D86069AE 1108 | 6E00002429382F16 1109 | 6E00002C57BE5139 1110 | 6E00002C65A4E1F5 1111 | 6F00000026DDBC8C 1112 | 6F0000014791C6A8 1113 | 6F000003F0E90073 1114 | 6F00000D72C8D872 1115 | 6F000011CE846C1D 1116 | 6F000012A12D2664 1117 | 6F00001FECF3402E 1118 | 6F0000210F1C3F57 1119 | 6F00002743107102 1120 | 6F0000292EDB04BD 1121 | 700000011C1163AD 1122 | 700000017291D93B 1123 | 70000001FCC20851 1124 | 70000004EA157396 1125 | 7000000A59388E51 1126 | 7000000AC3B10AE8 1127 | 7000000CC57EDF11 1128 | 700000169897C702 1129 | 700000179342BE76 1130 | 7000001D8290EF12 1131 | 71000000B0EB7515 1132 | 7100000679E1276A 1133 | 71000008D1E5C206 1134 | 710000107334DF38 1135 | 71000014C496BF27 1136 | 7100001635B486D0 1137 | 71000017F0227E0D 1138 | 7100001DED3A48F0 1139 | 71000021760908AA 1140 | 7100002AEB8FA92D 1141 | 72000000396E86DA 1142 | 72000007F26EA243 1143 | 7200000AD8327E78 1144 | 7200000E5088D1C9 1145 | 72000017349CE1B7 1146 | 7200001C2C7E9AED 1147 | 7200001C7C96232A 1148 | 7200002183262778 1149 | 7200002772052E7E 1150 | 72000029379F2046 1151 | 7300000747D7E5E8 1152 | 730000075D505479 1153 | 7300000E3C0ED556 1154 | 73000021D99CB5A4 1155 | 7300002CD13D6CD4 1156 | 7300002DC5361513 1157 | 7300002F8B4985EF 1158 | 7300003ACE878FE1 1159 | 7300003E7E372B58 1160 | 73000040A0FCF5EA 1161 | 740000070BD3D8CA 1162 | 74000008B5AA3EE5 1163 | 74000009E693D242 1164 | 7400001004F624DA 1165 | 7400001CDA8071BD 1166 | 74000022C96A13F3 1167 | 74000023FCE83033 1168 | 74000027889999D9 1169 | 740000288F3CA2DB 1170 | 7400002BEF23D01D 1171 | 750000016D3F24C0 1172 | 75000004D0D428C1 1173 | 750000092D76C306 1174 | 750000097202254E 1175 | 7500000DB7600254 1176 | 7500001226A54A50 1177 | 75000015B880FFF2 1178 | 75000019992FA767 1179 | 7500001A7B9EB720 1180 | 7500001E8AA0B72D 1181 | 76000000F960587F 1182 | 76000001B32F3459 1183 | 76000008D1618D33 1184 | 760000090C6FA55C 1185 | 76000009376E7539 1186 | 76000009913FE00E 1187 | 760000101434185F 1188 | 76000010170AE09F 1189 | 76000011B4EE8327 1190 | 7600001896ED1346 1191 | 770000013F6297E9 1192 | 77000001989AD8A7 1193 | 7700000295F7B2B5 1194 | 770000065AC56A93 1195 | 7700000ADB13884A 1196 | 77000013BB4B0473 1197 | 77000013D7317AED 1198 | 77000014A64349B5 1199 | 77000014BEEE5A44 1200 | 7700001A8112D749 1201 | 78000000C0B3A12D 1202 | 780000011F7795F3 1203 | 780000077B9066ED 1204 | 7800000B98985E79 1205 | 78000010E37950FF 1206 | 78000011D25D8813 1207 | 780000128135CB2F 1208 | 78000014D14699AE 1209 | 78000016BB2FA36E 1210 | 7800002F0A73AD0D 1211 | 790000016D9B57F4 1212 | 79000002EF0B1E8F 1213 | 790000040324F486 1214 | 79000006F34A6942 1215 | 7900000CC13BDD3B 1216 | 7900000EE031C944 1217 | 79000011BAD1C159 1218 | 79000011C84B66DA 1219 | 79000016DD69FFF3 1220 | 79000017396071DC 1221 | 7A0000005BDCDA6C 1222 | 7A000001A2F19FCF 1223 | 7A000004F847FEF2 1224 | 7A00000C61E3275E 1225 | 7A000018A22EAA3D 1226 | 7A00001A4C741793 1227 | 7A00001F59950FE3 1228 | 7A000022EBFAE77D 1229 | 7A000023421431A7 1230 | 7A00002C20B96912 1231 | 7B000000EA356C70 1232 | 7B0000043FA08A33 1233 | 7B00000D35BF1921 1234 | 7B00000D96488496 1235 | 7B0000125E2DABC0 1236 | 7B00001270AB6CCE 1237 | 7B000013B43746DB 1238 | 7B000023BC37B80F 1239 | 7B000025EDAFF4B6 1240 | 7B00002A34E6C1C5 1241 | 7C000002AD83B79A 1242 | 7C000004DAD2D721 1243 | 7C00000C785B7838 1244 | 7C00000F331A50DA 1245 | 7C00000FBC3E2B31 1246 | 7C00001DA382EDCC 1247 | 7C00002160198DBC 1248 | 7C000021873DE5DE 1249 | 7C00002265400A86 1250 | 7C00002E98E79DBF 1251 | 7D0000009DC55B89 1252 | 7D000001BA262E4C 1253 | 7D00000277EB3F0D 1254 | 7D00000E7D38AE8F 1255 | 7D00000F67DC8EE8 1256 | 7D000019435C61AB 1257 | 7D00001B7F2FD473 1258 | 7D00001EC7240AC7 1259 | 7D00001ECFABBF6C 1260 | 7D00001F653D42FF 1261 | 7E0000003790E78A 1262 | 7E0000152D4515B3 1263 | 7E00001C684B1E0E 1264 | 7E0000213165E62B 1265 | 7E0000265943D24E 1266 | 7E0000275781C077 1267 | 7E00002930688C1A 1268 | 7E00002D26DD2C1A 1269 | 7E000033907F6BAF 1270 | 7E000037CB3D01DA 1271 | 7F00000835DB7F58 1272 | 7F0000109A77A077 1273 | 7F000018E1C87980 1274 | 7F00001C17574CD9 1275 | 7F00001F50750E1F 1276 | 7F000022DD6F03DF 1277 | 7F00002361F9D00A 1278 | 7F000026F4D7300F 1279 | 7F0000283272EA63 1280 | 7F00002BB6AD2EEC 1281 | 80000000A29888BB 1282 | 8000000531FBF5B0 1283 | 8000000DA84118E4 1284 | 8000000FBA0A5EAE 1285 | 8000001466ABA63B 1286 | 8000001BCFAE9E5D 1287 | 8000001EF4D5E61D 1288 | 80000020ED1B2EB5 1289 | 800000212CA7C3DA 1290 | 80000023F9FA7BE5 1291 | 8100000379BA3013 1292 | 810000039CE9CB43 1293 | 81000007D6B945E4 1294 | 81000011D61C70DE 1295 | 810000132DCECFCB 1296 | 810000150722E1A1 1297 | 81000016AA85A6A1 1298 | 8100001A27A42684 1299 | 8100001F70173266 1300 | 810000236C343A5B 1301 | 8200000422035F26 1302 | 8200000D553ED7EB 1303 | 82000013E858D2FD 1304 | 82000018A74961F4 1305 | 820000216EC29D2B 1306 | 820000217DA43F68 1307 | 820000248627BCFF 1308 | 8200002601D60413 1309 | 82000030E89E970E 1310 | 8200003B11A508AB 1311 | 83000002C77DCCBE 1312 | 83000005B76C1A73 1313 | 8300000C165C682D 1314 | 8300000D73623F30 1315 | 8300000F341AE2A5 1316 | 83000010CC3DFAB1 1317 | 83000013C8F759B3 1318 | 8300001497089806 1319 | 8300001909C6030E 1320 | 8300001AA7F62162 1321 | 840000004A1FFD82 1322 | 8400000BF0181DBD 1323 | 840000173B38B40E 1324 | 8400001EB55F7AB1 1325 | 84000022F1B79A12 1326 | 840000231BB4B652 1327 | 84000025A21A897B 1328 | 84000030133DA164 1329 | 8400003738F20ABB 1330 | 8400003A72711D72 1331 | 8500000C9AE08BE9 1332 | 85000022428CE92F 1333 | 8500002CBED9E54E 1334 | 8500002E8187C1D0 1335 | 8500002F428FF75F 1336 | 85000033A1CBCBE5 1337 | 85000041D7DF95D7 1338 | 8500004228FD5135 1339 | 850000488FE6D286 1340 | 8500004C3D513ED4 1341 | 8600000418672C17 1342 | 86000007FD6177B7 1343 | 86000009256FA22C 1344 | 86000009D01935E8 1345 | 8600000A103BE863 1346 | 8600000B47C2F918 1347 | 8600000C32CF7C40 1348 | 8600001C4BF69D38 1349 | 86000026239D2B01 1350 | 860000303FCF4861 1351 | 870000052111A4F9 1352 | 87000008824ADA6E 1353 | 8700000A9EF618CA 1354 | 8700000B2E78E301 1355 | 87000018ABBD23D8 1356 | 87000018C710952B 1357 | 8700001D50FBC54E 1358 | 8700001D570F12B6 1359 | 8700001F110C93A3 1360 | 8700001FBBCE8CF3 1361 | 880000107679EE22 1362 | 8800001A3FCC2502 1363 | 8800001F99F6C261 1364 | 880000218AA074CF 1365 | 88000021CF21C0D4 1366 | 88000024F5BCD3A9 1367 | 88000031A72E0969 1368 | 8800003A741B1224 1369 | 8800003AEA0A3F3F 1370 | 8800003E906B1F0D 1371 | 89000012A04A9AF4 1372 | 8900001CBC8F0B2A 1373 | 8900002E02DF5063 1374 | 89000034696683AB 1375 | 89000036619C51A7 1376 | 890000368087869B 1377 | 89000037116901B7 1378 | 89000037C4851086 1379 | 8900003882FBAEB4 1380 | 8900003C58E2AB4F 1381 | 8A000000C15D28F0 1382 | 8A000001FCCD3EE8 1383 | 8A000002910E60DB 1384 | 8A00000807A0C699 1385 | 8A00001581AC713A 1386 | 8A00001645A3CD60 1387 | 8A000018B49D9AC1 1388 | 8A00002732404F7D 1389 | 8A0000286E36DB44 1390 | 8A00003D11A03B38 1391 | 8B00000223257CA3 1392 | 8B000007722D70A2 1393 | 8B00000896066994 1394 | 8B00000A50131DA7 1395 | 8B00000BAEB39A9C 1396 | 8B00000EA62CCC3D 1397 | 8B0000125CF6B3FB 1398 | 8B00001D2AF2F616 1399 | 8B0000253FAEC39D 1400 | 8B00003121EC17E8 1401 | 8C000000A0371888 1402 | 8C0000021F145C8A 1403 | 8C00002606BC3837 1404 | 8C0000263597E5AF 1405 | 8C000027427E79A2 1406 | 8C000028C0A84F20 1407 | 8C0000290C4F3D5A 1408 | 8C0000293FA1CD28 1409 | 8C00002F31E42D7D 1410 | 8C00002F8C96BA07 1411 | 8D000000F2696092 1412 | 8D000004203B9987 1413 | 8D000004EE0E777D 1414 | 8D0000058DB35F15 1415 | 8D000010449AD651 1416 | 8D000017B1C4B41E 1417 | 8D0000187D508485 1418 | 8D0000222026D6AF 1419 | 8D0000227E0F1124 1420 | 8D0000234CD5EFEC 1421 | 8E0000025A95BBB3 1422 | 8E00000372D18A7E 1423 | 8E0000077260BE99 1424 | 8E00000E638D0D94 1425 | 8E000010B1CF2C93 1426 | 8E000013C3A0CE6B 1427 | 8E00001ADCCD38B2 1428 | 8E00001B5E2C2D6C 1429 | 8E00001F8E0CD03F 1430 | 8E0000255ED1DE23 1431 | 8F0000003264C87E 1432 | 8F00000149B57E1C 1433 | 8F00000A610811A7 1434 | 8F0000107AA2C643 1435 | 8F000013A1C1FD98 1436 | 8F00001517653ABF 1437 | 8F000015D67A8B0B 1438 | 8F000019745E37A1 1439 | 8F00001AF5DF5A28 1440 | 8F00001C9272D67E 1441 | 900000039FD3D781 1442 | 900000073273AD10 1443 | 90000007A4DB0E8E 1444 | 90000012BEC1F4B9 1445 | 90000014BA1A4C26 1446 | 900000183D4EC9E9 1447 | 9000001B4EF16AB3 1448 | 9000001CCA6F9F5D 1449 | 9000001E6B16320E 1450 | 90000021729D5B49 1451 | 9100000B102B7670 1452 | 9100000F7944020B 1453 | 9100001946E3A733 1454 | 910000214B1D9ED3 1455 | 91000023DDBCF70A 1456 | 9100003189F7E39B 1457 | 910000333F9320BF 1458 | 9100003420023772 1459 | 910000379FC9D11B 1460 | 9100003B67A57231 1461 | 92000001A6C7E793 1462 | 92000007168EC260 1463 | 92000008BFF47FCE 1464 | 9200000ADB929A71 1465 | 9200000B578C18F7 1466 | 9200000D1FDE6D3E 1467 | 9200000D93BDED88 1468 | 9200001003A0E894 1469 | 920000107B8FA677 1470 | 92000019E9FE51B9 1471 | 9300000A3ADAE607 1472 | 9300000B43CF3FEE 1473 | 9300000C4E858ED9 1474 | 93000015A9368CD5 1475 | 93000015E42FABC7 1476 | 9300001A66209E10 1477 | 930000239296029D 1478 | 93000023EB73E80D 1479 | 9300002693752652 1480 | 9300002C81C76D54 1481 | 94000005146AAEC0 1482 | 9400000D090C494C 1483 | 9400000D686D2577 1484 | 940000116C490F9E 1485 | 9400001330816D19 1486 | 9400001382A08AB4 1487 | 94000022D97B51C7 1488 | 940000233B623E06 1489 | 9400002447ECC357 1490 | 9400002924055398 1491 | 950000005EF400FE 1492 | 9500000143EC57C2 1493 | 95000006DB800C2D 1494 | 95000007DBA08CAF 1495 | 9500000A6CE4A09E 1496 | 9500000C245B6549 1497 | 9500000C79A4C477 1498 | 9500000F517CC782 1499 | 95000012298229C7 1500 | 950000129D8EC6C1 1501 | 96000000DAD5DEC6 1502 | 96000004444FAB51 1503 | 960000058C1C45DD 1504 | 96000009387BE604 1505 | 9600000DAF63A6B4 1506 | 9600000DBFCAF050 1507 | 9600000E3B3F4FBE 1508 | 960000195157FCD6 1509 | 9600001AFBF6973F 1510 | 9600001BF4A2CD7C 1511 | 97000001335C230A 1512 | 9700000405DF126E 1513 | 970000044C8F6D4C 1514 | 9700000A48349B68 1515 | 9700000B319E5B53 1516 | 9700000D28FC2909 1517 | 9700000E42A641A6 1518 | 97000011CA66F6E2 1519 | 9700001617AA8E43 1520 | 9700001AF3F39C34 1521 | 980000075FB08632 1522 | 9800000B0BC4DFD1 1523 | 98000012D4DA4F99 1524 | 98000019A068B1FD 1525 | 9800001AC31BCA0F 1526 | 9800001BFE13240C 1527 | 9800002145B313CA 1528 | 98000023F9FA6893 1529 | 980000256DD5D88D 1530 | 98000028E5319479 1531 | 990000010E9D4EDD 1532 | 9900000270E4DD02 1533 | 990000083D62A0E8 1534 | 99000008750210A0 1535 | 99000010AD223A9F 1536 | 99000017454CFFC6 1537 | 9900001A798F8761 1538 | 9900001BDCFA3FD7 1539 | 9900001E166C814E 1540 | 9900002415140586 1541 | 9A000006B5187594 1542 | 9A000007B86412E7 1543 | 9A0000084AE37983 1544 | 9A00000916378EE0 1545 | 9A00000ECF5DC714 1546 | 9A00000FD41EB19D 1547 | 9A00001721382709 1548 | 9A000021071D98AA 1549 | 9A000023B70257F1 1550 | 9A00002427051BFF 1551 | 9B0000020225A747 1552 | 9B0000037C7F81B3 1553 | 9B0000038B6DA1F7 1554 | 9B000003C758DBA6 1555 | 9B00000414F1C086 1556 | 9B000009CF9BB02B 1557 | 9B00000F90063A7C 1558 | 9B0000146996259D 1559 | 9B000016172B62A8 1560 | 9B000016669A77F0 1561 | 9C0000029D6491FB 1562 | 9C00000C47941E55 1563 | 9C00000FC2F82937 1564 | 9C00001080B6A8BF 1565 | 9C000011FC95FB41 1566 | 9C0000130B79BD13 1567 | 9C000017F3CAC836 1568 | 9C0000198DF53A9B 1569 | 9C00001B8B907873 1570 | 9C00002D7D0C0572 1571 | 9D000000C9B685F2 1572 | 9D00000712678EC2 1573 | 9D000007E2932295 1574 | 9D0000130EE27CF7 1575 | 9D0000178E7D11CC 1576 | 9D000019C3DF8EA1 1577 | 9D00001CF470369B 1578 | 9D00001E6B2D2BBD 1579 | 9D000024193C66AC 1580 | 9D000024F495AD06 1581 | 9E000018D34E7E11 1582 | 9E000018F52E93C1 1583 | 9E00001CEEEF734F 1584 | 9E00001FC1D87203 1585 | 9E00002BADC7597E 1586 | 9E00003198D452E4 1587 | 9E000039AE309B13 1588 | 9E00003B91EAB779 1589 | 9E00003E6F73383C 1590 | 9E00003E7CB918F9 1591 | 9F00000843C21955 1592 | 9F000012062C86C1 1593 | 9F0000134E1E8C77 1594 | 9F00001438982CA0 1595 | 9F00001902BB665B 1596 | 9F00001A9A13B42B 1597 | 9F000020511E6DA5 1598 | 9F0000239A51A38B 1599 | 9F0000326CA56BFB 1600 | 9F00003522825D66 1601 | A00000095E446945 1602 | A000000E83377C80 1603 | A00000116A8793F5 1604 | A0000016291A777A 1605 | A00000177A183186 1606 | A0000019C68386C1 1607 | A0000019F75271E9 1608 | A000002034268CA4 1609 | A0000020533D912A 1610 | A0000022348134D5 1611 | A100000050FB74B8 1612 | A100000A00F175E2 1613 | A100000B7081EEF8 1614 | A100000C3C539920 1615 | A1000013E8E56DF4 1616 | A100001429222040 1617 | A10000149FCD9F69 1618 | A1000014A88853EF 1619 | A1000024EB434709 1620 | A100002783FE2CA1 1621 | A20000008EF61D46 1622 | A20000014CD73297 1623 | A2000007EEC2CC1D 1624 | A2000010B945433B 1625 | A2000017811A76FF 1626 | A20000198C570A4B 1627 | A2000025A7618622 1628 | A200003667CE0EE2 1629 | A2000040D33DCB0E 1630 | A200004440E12A47 1631 | A30000002A8C3707 1632 | A3000002DF85EEE6 1633 | A300000334FBE6C8 1634 | A3000007256B17E8 1635 | A300000FA05A40A6 1636 | A30000188B9E409E 1637 | A30000190CE5187E 1638 | A30000241C5F0F69 1639 | A300002902ECADBD 1640 | A300002A9839F772 1641 | A400000209D16335 1642 | A4000003B5EF4FA7 1643 | A400000ABEA806C5 1644 | A400000E36AADAB4 1645 | A400000F7045641D 1646 | A40000126BFB8B6C 1647 | A400001B5DC25E71 1648 | A400001C5BBA6350 1649 | A4000027AA82269A 1650 | A400002D08C5C930 1651 | A50000006DDB572C 1652 | A5000001E2804AC2 1653 | A5000002115883BA 1654 | A5000004898463F1 1655 | A500000729849240 1656 | A5000007DEB4DBAE 1657 | A500000C889DE093 1658 | A5000011F6330D26 1659 | A500001635F78FD7 1660 | A500001857ABD8B1 1661 | A6000005117836F4 1662 | A6000006317D46C6 1663 | A6000006F5E3EF22 1664 | A6000009A81C8991 1665 | A600000A41FF26A1 1666 | A600000A6714C99E 1667 | A600000C5F9E5360 1668 | A600000D169105F9 1669 | A600000DE94B38EA 1670 | A6000014982E79EB 1671 | A700000086A1B346 1672 | A700000A6D2C395D 1673 | A700000ABBECD21C 1674 | A70000102F39054B 1675 | A7000010E7773BCF 1676 | A7000010FD99FDCB 1677 | A70000110010E555 1678 | A70000144344B2A4 1679 | A7000018F47FCA3B 1680 | A70000192D1A34A6 1681 | A80000012E4F14A6 1682 | A80000072429E9F4 1683 | A800000CBD006DA3 1684 | A800000EBE535BA6 1685 | A800000FC769B20C 1686 | A800001080DF3F78 1687 | A80000129CDA18B0 1688 | A8000024780D4CA2 1689 | A800002493985515 1690 | A800002756A85C9D 1691 | A9000003B82AF210 1692 | A9000003EAB79151 1693 | A9000005C96B1D62 1694 | A9000005D4C52BC0 1695 | A900000BBDED1954 1696 | A900000D82DE5CDC 1697 | A900000FE80D93E8 1698 | A9000017E45386C9 1699 | A90000192DB13644 1700 | A9000020FA250D8D 1701 | AA0000017954C94D 1702 | AA00000AEAC63FA3 1703 | AA00000E55287F25 1704 | AA00000FDD41C089 1705 | AA0000113ADA3BDB 1706 | AA000017350E6D60 1707 | AA000019ED03EDD1 1708 | AA00001C02531F96 1709 | AA0000209752DF66 1710 | AA000025F9FEEC1E 1711 | AB000000DFABDCEE 1712 | AB000000E306DC22 1713 | AB00000EDE236435 1714 | AB0000129E352719 1715 | AB000017B85128AA 1716 | AB00001BD9E3A158 1717 | AB00001F004536A1 1718 | AB000029CC488457 1719 | AB00002A15758092 1720 | AB00002B3F217A00 1721 | AC0000022A0E43F1 1722 | AC0000034B56FFC3 1723 | AC00000AA8567402 1724 | AC00000F06CE7BD7 1725 | AC0000105378E415 1726 | AC000015192A29C7 1727 | AC00001B2A03C188 1728 | AC00001C4CDC7FB3 1729 | AC000020559F6A36 1730 | AC000022308CB6D6 1731 | AD000002ACA5E876 1732 | AD0000063BBFA625 1733 | AD00000C26F483AD 1734 | AD00000D86C53AE5 1735 | AD0000110F32C94B 1736 | AD00001277E47ECF 1737 | AD000012E589B810 1738 | AD000013EE864211 1739 | AD0000164AFDBB00 1740 | AD00001BC4F22D0B 1741 | AE000000E2B592A9 1742 | AE000000EA77E6DA 1743 | AE0000048AE95504 1744 | AE000005064E4CE1 1745 | AE000007277FE82B 1746 | AE0000076E6D9B6A 1747 | AE00000A4971C179 1748 | AE00000D1571C2DB 1749 | AE00001097CB9CE9 1750 | AE0000145AC41C44 1751 | AF000002EC31DF91 1752 | AF00000912165C55 1753 | AF00000ADB29E54F 1754 | AF00000ECC5BBC93 1755 | AF0000153EB0DF31 1756 | AF00001D0E9A900D 1757 | AF00001D1593CE08 1758 | AF0000220085A29C 1759 | AF00002602A49141 1760 | AF000029C4B325DA 1761 | B00000015E782E19 1762 | B00000031A077707 1763 | B00000033125507D 1764 | B000000383BA809F 1765 | B00000063301BD5B 1766 | B000000CCC61D159 1767 | B000000FB8053CB8 1768 | B0000011E9C5717D 1769 | B000001226B44B9E 1770 | B00000169818C212 1771 | B1000000DFE676CA 1772 | B10000022724AC07 1773 | B10000057180662F 1774 | B100000AA03F715E 1775 | B100000AB3477DA5 1776 | B100000B3A936D66 1777 | B100000F4A669646 1778 | B1000016D8247388 1779 | B100001D5ACEBE4E 1780 | B10000255397385E 1781 | B200000420DFB196 1782 | B2000004A135FC51 1783 | B20000051F22728A 1784 | B2000018E2943F8A 1785 | B200001E5669311D 1786 | B20000215512CBDF 1787 | B200002479B51F42 1788 | B2000027AB5DE5A2 1789 | B200002EC4E52891 1790 | B2000033F7AE976F 1791 | B3000007C09519EE 1792 | B300000CA042747D 1793 | B300000D41910076 1794 | B300000E8E553EC1 1795 | B300000FA4412587 1796 | B300001DAA1F9B85 1797 | B300002096D3402C 1798 | B300002719162BC8 1799 | B300002C961720FB 1800 | B300002D134520E7 1801 | B4000000242C72A8 1802 | B4000000C13FE2DE 1803 | B4000008D00ED50E 1804 | B400000ED4531A17 1805 | B4000010BC518140 1806 | B4000017F2B382F8 1807 | B4000019EF59DE64 1808 | B4000024C8B5B3C0 1809 | B4000031008622E9 1810 | B4000038F05B77FD 1811 | B500000317FC177A 1812 | B50000039D2C95AC 1813 | B5000003DFC1FFB1 1814 | B5000007B5A60CA4 1815 | B500000F469A52B7 1816 | B5000011546E388F 1817 | B50000121B4060DF 1818 | B5000015FEF0BE87 1819 | B50000276BECD430 1820 | B500002DCF8B43D2 1821 | B600000B55E3405D 1822 | B600001BB47B969A 1823 | B600001F1BD70809 1824 | B6000026C754C02B 1825 | B6000027DEA4AF41 1826 | B60000327D4ABDD0 1827 | B60000359207782A 1828 | B600003640476C98 1829 | B600003C8F6C41DC 1830 | B6000040651DF02C 1831 | B70000037312A590 1832 | B70000095E5EC4F1 1833 | B700000C37261F0E 1834 | B700000D1A01FD70 1835 | B7000010E742287D 1836 | B70000181629B4E1 1837 | B7000021608D5664 1838 | B7000033E7102F0B 1839 | B7000035A131B443 1840 | B7000037C2699AAC 1841 | B8000000FF6EA9C1 1842 | B8000002B3FDF9E6 1843 | B800000591A451E5 1844 | B8000007BA4135B0 1845 | B800000C692A2EB9 1846 | B800001137783B01 1847 | B80000138B983A9A 1848 | B8000013A68AA12E 1849 | B800001B5DA63587 1850 | B800001F09346AAB 1851 | B9000000FE142551 1852 | B90000052B5E0995 1853 | B90000091D58BC3E 1854 | B900000A1A5D8331 1855 | B900000B8284F0FC 1856 | B900000C07C79534 1857 | B900000D9AC4D1A4 1858 | B900000E18756A9C 1859 | B900000F04464D92 1860 | B90000115EDEDDD6 1861 | BA00000074A0D501 1862 | BA0000019EC0CB43 1863 | BA000002C3221F97 1864 | BA0000045FB1483E 1865 | BA00000C17DC8B4F 1866 | BA00000C19F5885B 1867 | BA00000D764614D4 1868 | BA000010A12A3EA7 1869 | BA00001135EB1CD6 1870 | BA000011C1947961 1871 | BB000003A12A797E 1872 | BB00000664C08BD6 1873 | BB000006DB20B794 1874 | BB00000A8C7B2C05 1875 | BB00001067296B26 1876 | BB000019BE1FB747 1877 | BB00001F2F10875A 1878 | BB00001F826553D1 1879 | BB000026D04D28D8 1880 | BB00002C27D98D7B 1881 | BC0000025A9CAD5A 1882 | BC000002DFCDA79B 1883 | BC000003B8CADA57 1884 | BC00000AA0278C4E 1885 | BC00000DF1ACB462 1886 | BC00000FD8044A7F 1887 | BC00001859C989F5 1888 | BC00001E53910449 1889 | BC0000214919DFE6 1890 | BC00002664C5E80A 1891 | BD0000026CD5EF37 1892 | BD000005B75990E0 1893 | BD000008A07EE9DD 1894 | BD00000D58625063 1895 | BD000010D54A111C 1896 | BD000012CC1EAB96 1897 | BD00001FD1409A30 1898 | BD00002A3A3EBF89 1899 | BD00003269FC2070 1900 | BD0000348F915DA0 1901 | BE0000003A15D445 1902 | BE000001ECE73168 1903 | BE00000B14BD45F1 1904 | BE00000B37CE43FD 1905 | BE00000E532F1AA0 1906 | BE00000FFF96B167 1907 | BE000011FF56B98B 1908 | BE000012094DE4DE 1909 | BE0000123C4D6B04 1910 | BE00001C32D17A63 1911 | BF00000224C87E3B 1912 | BF000004E36EDCCA 1913 | BF00001D53F713F1 1914 | BF00001EDB777E80 1915 | BF000024E949559F 1916 | BF00002B123DFB9B 1917 | BF00002B5EC6E382 1918 | BF00002EB1C7B97B 1919 | BF000030012A5E42 1920 | BF000038D9B6D9B0 1921 | C00000006D82339C 1922 | C00000016439EB97 1923 | C00000044F8E12A2 1924 | C0000007F0DE93B5 1925 | C0000009E95235B3 1926 | C000000A6F3659B9 1927 | C000000B4458AA7A 1928 | C000000B63A84AFA 1929 | C000000CC57FC8A7 1930 | C000000E3F5D8245 1931 | C1000003799CAD13 1932 | C10000041F419236 1933 | C100000D7FC1A88C 1934 | C10000109C63747F 1935 | C10000133E107A9F 1936 | C100001469BCEAA7 1937 | C1000018A160FBAA 1938 | C100001CFA136FA8 1939 | C100001D085439CB 1940 | C100001D50B7858D 1941 | C20000075FB9442F 1942 | C200000A11FC872F 1943 | C200000B8E0852B9 1944 | C200000B98505FE6 1945 | C2000012DC0DADDE 1946 | C2000013CC35849C 1947 | C200001607C1B90B 1948 | C20000281AF94568 1949 | C2000028C8007ABE 1950 | C20000297D354750 1951 | C300000198CA5152 1952 | C30000060B38F520 1953 | C30000072B54D048 1954 | C3000007D4F5E113 1955 | C30000083E4D0449 1956 | C300001302F60DD4 1957 | C30000186B23DA8C 1958 | C3000018FD8C2859 1959 | C300001C07BA254C 1960 | C30000250B1D3273 1961 | C400000177F9DDC7 1962 | C4000008188EC917 1963 | C40000099C30523D 1964 | C400000D6C786082 1965 | C4000016D154B76B 1966 | C40000186FC58D2B 1967 | C400001A36908C1F 1968 | C400001BC5814106 1969 | C400001F39E277DB 1970 | C40000253BCEBB87 1971 | C50000010EF154E9 1972 | C50000021E5316F5 1973 | C5000002EBE31863 1974 | C500000756482F91 1975 | C500000AAA4A9D61 1976 | C500000D34A3A13D 1977 | C50000106226C61D 1978 | C5000012E732D616 1979 | C500001835D1160A 1980 | C50000185F818D02 1981 | C60000011DFA4786 1982 | C600000EF68450A7 1983 | C6000013C866D4BA 1984 | C6000014152975B2 1985 | C6000015202E2F3F 1986 | C6000018E21B9482 1987 | C60000240FE20A18 1988 | C6000028121898DB 1989 | C60000350D48B374 1990 | C6000047958F2C0B 1991 | C700000A0F664BBF 1992 | C700000BB5D7F9F1 1993 | C700000C6BD3E641 1994 | C700000F20038947 1995 | C7000011CA1C8FAB 1996 | C7000020A9CC9654 1997 | C700002B3CC9FFEE 1998 | C700002C4169E2EB 1999 | C7000037ED0442C7 2000 | C700004186F48A1F 2001 | C80000006BB34365 2002 | C80000097E9F1EED 2003 | C8000016FA22D6E0 2004 | C800001AC9753C00 2005 | C800001FB4956CCB 2006 | C80000227E313C46 2007 | C80000240B39ED39 2008 | C800002A79B0DE78 2009 | C800002E3BC6BA08 2010 | C80000340FF157BD 2011 | C9000001CE35FFC9 2012 | C90000025E8A4F0F 2013 | C90000123802EF13 2014 | C900001CE183096A 2015 | C9000022F87FF3F6 2016 | C90000246F5C15EE 2017 | C900003CD2AE0F9F 2018 | C900003F026BF66C 2019 | C900004549D329E7 2020 | C900004E62AC59B1 2021 | CA00000264EDF6A0 2022 | CA0000035886778A 2023 | CA0000054F5D4879 2024 | CA000005711AE9DC 2025 | CA0000077CB150FF 2026 | CA000008E085D2C7 2027 | CA000009225B3E37 2028 | CA00000BC7F2242F 2029 | CA000012905C0498 2030 | CA0000151264770E 2031 | CB000000622B624C 2032 | CB00000189F231F2 2033 | CB000009102EACB9 2034 | CB00000A6677086A 2035 | CB00000B0A8EC1CC 2036 | CB000018F00B3FB5 2037 | CB00001C56EE6A72 2038 | CB000022065480C6 2039 | CB0000261C1CE461 2040 | CB00002943D28BA3 2041 | CC000001CE930059 2042 | CC00000271B0F9AA 2043 | CC0000035CA2FA2D 2044 | CC000008585DB7C8 2045 | CC00000BB7675928 2046 | CC00000BCAE8984C 2047 | CC000013DBB5ECD3 2048 | CC000016100C0759 2049 | CC00001BB454F91B 2050 | CC00002E0C8B98C8 2051 | CD000003AA2F9B54 2052 | CD00000AAD94B392 2053 | CD00000B1E5FA52C 2054 | CD00000E98C65308 2055 | CD000013A2DD8584 2056 | CD000015690FFFF8 2057 | CD00001618A854E5 2058 | CD00001A5CC3D61B 2059 | CD00001B97ADD262 2060 | CD000020584C8E76 2061 | CE0000035ABB2F3C 2062 | CE00000EA2A90C4E 2063 | CE000011710452F3 2064 | CE000015544AAF66 2065 | CE000015D27CA015 2066 | CE00001A841CE9E4 2067 | CE00001E8EFDDDEF 2068 | CE00002867CA1374 2069 | CE0000339A8DA7F7 2070 | CE00003432F025EB 2071 | CF00000636218A1B 2072 | CF00001027DEA8E6 2073 | CF000013D609F41D 2074 | CF0000156D8269CA 2075 | CF000017CF497029 2076 | CF00001A6E1B7415 2077 | CF00001BD8604F38 2078 | CF00002922C9CC30 2079 | CF00002A61E69233 2080 | CF0000336297AE66 2081 | D00000000F7ABBD6 2082 | D0000000E77C5CA4 2083 | D000000123DE7971 2084 | D0000001C9B79D3B 2085 | D0000003075A0E29 2086 | D00000030D316D8A 2087 | D0000005E5C90546 2088 | D0000006857A551E 2089 | D00000084D55038C 2090 | D0000008C00EDC6B 2091 | D1000003397BCC7A 2092 | D10000148F9B1C9C 2093 | D100001E7BCA7A24 2094 | D1000022F7F12993 2095 | D100002419D378AC 2096 | D10000260F212E9E 2097 | D100002A2CB35FEC 2098 | D100002C569F979F 2099 | D1000031675F2ACB 2100 | D100003C8F390C05 2101 | D20000008EC3B483 2102 | D20000071536A4E1 2103 | D200000BF46F8B87 2104 | D200000C45B96FEC 2105 | D200000D710AC4F2 2106 | D200001305122451 2107 | D200001B68C86114 2108 | D2000020409755F0 2109 | D200002204454916 2110 | D200002A7A49F796 2111 | D3000005289AEF52 2112 | D3000006A774D19B 2113 | D3000009567535C9 2114 | D300000E11B85A91 2115 | D300000E9799CA9C 2116 | D300000FED9453FA 2117 | D3000014E9788864 2118 | D300001B035610F6 2119 | D300001FD7AB612B 2120 | D30000321044EFCD 2121 | D4000003ABAC2B77 2122 | D40000085C10E91F 2123 | D4000009A58639A5 2124 | D400000B7FF3078B 2125 | D400000E442399B7 2126 | D400000E7CEE5D39 2127 | D4000013C314A154 2128 | D400001B197F44D0 2129 | D400001C9ABC54D8 2130 | D400001D73B33E38 2131 | D50000041CB6BB34 2132 | D500000694B0FC46 2133 | D500000758AD68F5 2134 | D500000AE4F61DB5 2135 | D500001065C0F85B 2136 | D5000019DC67028F 2137 | D5000020CCA35739 2138 | D50000251EDAFA6F 2139 | D500002DD7A416FD 2140 | D500002F6D510594 2141 | D600000222F387B6 2142 | D600000473D3ECE3 2143 | D600000876F8B757 2144 | D600000B1CADB21A 2145 | D600000C107C026D 2146 | D6000012621661B0 2147 | D60000137EB4A6A7 2148 | D600001AEDC7444F 2149 | D60000212F148FE8 2150 | D60000224DD33798 2151 | D700001979663BD0 2152 | D700001B068E46A8 2153 | D700001FEC4B04CE 2154 | D70000240BF77153 2155 | D7000028B2F91CA7 2156 | D700002D320AD29F 2157 | D700002E6B1CB921 2158 | D700002F03F0E4E3 2159 | D7000031DB81AA1F 2160 | D700003571BFE46F 2161 | D80000015419BC2B 2162 | D800000B0B071942 2163 | D800000C948A5D47 2164 | D800001910E59EEF 2165 | D8000028912C9169 2166 | D800002BEC9C4EB7 2167 | D8000030BC8CEA40 2168 | D80000321FD72E80 2169 | D80000370F558479 2170 | D80000403C02E6E2 2171 | D900000080C245DB 2172 | D90000053B2685CA 2173 | D900000B18C9F7AD 2174 | D90000107F2514F8 2175 | D9000010FC892643 2176 | D900003094806E69 2177 | D90000343D4855D5 2178 | D900003F62DCC77A 2179 | D900004332F744AF 2180 | D900004B5524E9AE 2181 | DA0000011A8AFE76 2182 | DA00000A01EAA3D8 2183 | DA00000BFF6001FB 2184 | DA00000D521E4491 2185 | DA00000E7197E4CE 2186 | DA0000134A642354 2187 | DA00002146A592DD 2188 | DA000025A1087146 2189 | DA0000320EBE1C88 2190 | DA00003234B661D8 2191 | DB000000773DCE20 2192 | DB00000BAC1B2BA4 2193 | DB0000108E1F451B 2194 | DB00001150B265BE 2195 | DB0000121BB46304 2196 | DB000018CD287F5E 2197 | DB000018D9B42BFE 2198 | DB00001BB68AA86D 2199 | DB00001E6F8FE71D 2200 | DB000020ABC52469 2201 | DC00000269D7B72F 2202 | DC00000A600D1D52 2203 | DC00000CD5A1D3D0 2204 | DC00000E9CFB9DB7 2205 | DC00000F52CC2CE9 2206 | DC000010901412D6 2207 | DC00001336F80BBD 2208 | DC0000146036B8E9 2209 | DC000019AA7F42BE 2210 | DC00001C744783DE 2211 | DD000000D1EB40FB 2212 | DD0000028335B9F6 2213 | DD000006DCF243AC 2214 | DD00000E915D6943 2215 | DD000010E30D274F 2216 | DD00001346E3726C 2217 | DD000013592A5607 2218 | DD0000183457E7CB 2219 | DD00001955E66847 2220 | DD00001DC3E31748 2221 | DE0000000043C1F6 2222 | DE000001E161D705 2223 | DE0000035F2C1E2C 2224 | DE000007CDF32C9A 2225 | DE00000C58EB7B58 2226 | DE00001045274DB5 2227 | DE0000111AFB133D 2228 | DE0000115A66447A 2229 | DE00001243464656 2230 | DE000014420FF8A4 2231 | DF000001394C6B36 2232 | DF0000032CBF4B9B 2233 | DF000003FE27F155 2234 | DF000009B64CF550 2235 | DF00000B4BA420E6 2236 | DF00000C16EB21DA 2237 | DF00000DC7A82995 2238 | DF00000E7FDE6A61 2239 | DF000012ECB080E8 2240 | DF000013B79AACA7 2241 | E000000181330682 2242 | E000000273A6926B 2243 | E0000003668811D1 2244 | E00000070695AE9F 2245 | E0000008A779DADC 2246 | E000000BE511EAFC 2247 | E000000C20931AD9 2248 | E000000DF59C87C1 2249 | E000001106D64E26 2250 | E0000012304AD3A2 2251 | E10000128100E9CA 2252 | E1000013D76BBA96 2253 | E1000014E3B35B06 2254 | E1000015ECB16A81 2255 | E100001BCC04A60B 2256 | E100001D40F289B0 2257 | E100001D650552A6 2258 | E100002AD00B263C 2259 | E100002CC7CCD25D 2260 | E1000038917B79CB 2261 | E2000004C196BB41 2262 | E200000528E84BEF 2263 | E2000008FB009542 2264 | E2000009069C3692 2265 | E200000D01EE8997 2266 | E2000013267C107D 2267 | E200001AEB583C06 2268 | E2000021F6808860 2269 | E2000022E3D76AED 2270 | E20000288382AE0D 2271 | E3000001AF1AE16E 2272 | E300000367E70F59 2273 | E3000005BAAE2B1D 2274 | E3000008BC7F7B9D 2275 | E300000AD93A0625 2276 | E300000B95B3E20A 2277 | E3000013C6E6A7EC 2278 | E300001418286B52 2279 | E30000192731FD7E 2280 | E300002170B52F83 2281 | E40000002671FE82 2282 | E40000012322368B 2283 | E40000052B142EEF 2284 | E400000E6B235943 2285 | E400000E789F038A 2286 | E4000011A17A2B05 2287 | E4000020FEBDF2A7 2288 | E4000021CA16A43F 2289 | E4000027AC4E743C 2290 | E400002E7EA782FC 2291 | E5000001C84236C1 2292 | E5000006004CC958 2293 | E5000007785D4961 2294 | E500000EE6878C72 2295 | E50000122B853B05 2296 | E5000013DD3547DA 2297 | E500001648DF7E69 2298 | E5000016701770BA 2299 | E50000188F8AA782 2300 | E500001F98E8E973 2301 | E6000001C28A1CEA 2302 | E6000001C8D2B86B 2303 | E6000005BFBC5694 2304 | E60000064121C234 2305 | E6000006ACB99D35 2306 | E6000007BC756627 2307 | E6000011F612AA8F 2308 | E6000012D46E4752 2309 | E600001C3F8DD820 2310 | E60000228742710D 2311 | E700000245EC4960 2312 | E70000072C3779B0 2313 | E7000009A6946BAD 2314 | E7000016728E5F74 2315 | E700001C02E9B2F8 2316 | E700001DA2CEF09D 2317 | E70000235E6F149D 2318 | E700003281AB9E43 2319 | E7000044ACDF8594 2320 | E700004C1AC49420 2321 | E800000124C52A4B 2322 | E800000142E46EA8 2323 | E800000158910551 2324 | E800000A57084824 2325 | E800000B0F7B4286 2326 | E800000B2D2B35A8 2327 | E8000012D9091E2B 2328 | E8000018DE41CF78 2329 | E800001AA7D15E51 2330 | E800003FDCAE7661 2331 | E90000005EFCD90D 2332 | E90000023B956DFF 2333 | E9000003D75EBA71 2334 | E9000004C1674555 2335 | E90000074784761B 2336 | E900000D43F2F642 2337 | E9000015230CAC0A 2338 | E900001CA7C94D44 2339 | E900001F8CBCA2CF 2340 | E9000026B953CDF8 2341 | EA0000005EF48F92 2342 | EA000007977077C3 2343 | EA00000A33842A84 2344 | EA00000A9B5B0EE2 2345 | EA00000D3F71EDBD 2346 | EA000011C79336EC 2347 | EA00001F4D4E6ED7 2348 | EA000022B1F225DD 2349 | EA000022CDC0D09C 2350 | EA00002714D2DD20 2351 | EB0000001800B592 2352 | EB0000009CA76F47 2353 | EB00000239599438 2354 | EB0000067181E1D4 2355 | EB000009AA7BF01D 2356 | EB00000A59FA52CB 2357 | EB00000AB23FD056 2358 | EB00000B72FCDB72 2359 | EB00000D79DB0E37 2360 | EB00000FD5D20EC2 2361 | EC00000078C37219 2362 | EC00000475DB4CF3 2363 | EC0000053C8E84B8 2364 | EC000005C247BE02 2365 | EC00000854B4E0E5 2366 | EC00000C5EC1B0F6 2367 | EC000014AB8A1621 2368 | EC00001822E8E1B0 2369 | EC0000203E88E8EC 2370 | EC00002518F37C67 2371 | ED0000059D8A1FEF 2372 | ED000008CCF79A4F 2373 | ED000014F9ABD1B1 2374 | ED000022755227FE 2375 | ED000024868AF793 2376 | ED00002826363CA5 2377 | ED000028C2E04B46 2378 | ED00002CA16DE545 2379 | ED00002F368201A6 2380 | ED000030280220A9 2381 | EE00000543ADB1B8 2382 | EE00000980DB8CCE 2383 | EE00000B8D42FE61 2384 | EE00000BC29311E0 2385 | EE00000FFC20DCBE 2386 | EE00001F63516A4E 2387 | EE0000219ECC2078 2388 | EE000032CE3FCAA3 2389 | EE0000369F002F7D 2390 | EE000038C805D91F 2391 | EF0000023D83C2F5 2392 | EF000003D7B3DC0C 2393 | EF0000097E893A6D 2394 | EF00000DAFD6A508 2395 | EF0000130A7FFA4F 2396 | EF00001422652629 2397 | EF00001C280FA26C 2398 | EF00001DB14A4DD4 2399 | EF0000222DD32CA8 2400 | EF0000293911CFE8 2401 | F0000000606760CE 2402 | F000000CFCAA9AE5 2403 | F000000EF1DBD400 2404 | F000000F285C17BE 2405 | F0000012D51CFE7D 2406 | F0000012FA48489E 2407 | F00000131F865A6B 2408 | F000001512EE8D29 2409 | F00000174A27C858 2410 | F000001DDB5A0FE0 2411 | F1000006B90E197C 2412 | F10000088B731AE0 2413 | F10000138956ED75 2414 | F100001C092F0ADC 2415 | F100001C9CFC7A9C 2416 | F100002939E39625 2417 | F100002B7E6B4F1E 2418 | F100002BDB9986AF 2419 | F1000033C448D0EC 2420 | F100003B1EE76E48 2421 | F20000000762E98C 2422 | F2000009C265C9F0 2423 | F20000135732FEA3 2424 | F200001E2EF2A7DE 2425 | F2000024750CCFDE 2426 | F2000026910B69E5 2427 | F200002C1814CF06 2428 | F2000030CD78C1C2 2429 | F2000032164970AD 2430 | F200003386FAE23C 2431 | F3000000554DB1BE 2432 | F30000009749D08F 2433 | F3000003036901C0 2434 | F3000003B9B44270 2435 | F300000CE021ADEA 2436 | F300000CF4BD4BF5 2437 | F300000D2A197AC8 2438 | F300000FA2B8E900 2439 | F3000010B8DE73DB 2440 | F30000132EB3EEE2 2441 | F40000013830C34C 2442 | F40000131DF14E56 2443 | F4000013E3534834 2444 | F400001FE9E4B713 2445 | F4000020BD4E9BCB 2446 | F4000027CE1B360C 2447 | F40000374BF7B1E7 2448 | F40000542C9E61F1 2449 | F40000554530FF6E 2450 | F400005BAD818407 2451 | F50000082FF10FAA 2452 | F500000E9170CC52 2453 | F500001AB3691645 2454 | F500001C0D1B1745 2455 | F500001F09CA07F7 2456 | F5000029A5C1810E 2457 | F5000029A90CC0E9 2458 | F5000029EC5967A3 2459 | F5000029FD87BF1A 2460 | F500002A548E808D 2461 | F60000058D63ACEB 2462 | F6000009C1B4F130 2463 | F600000BCE6216AA 2464 | F600001183A2530E 2465 | F6000012B939C2B8 2466 | F6000015A4033033 2467 | F60000163649AD4A 2468 | F6000019F3EFD60F 2469 | F600001BA6DB064E 2470 | F600001E1F73B296 2471 | F700000363F7A5B9 2472 | F700000FD6843395 2473 | F700001258C99AFA 2474 | F7000015139356FE 2475 | F70000164FE1B82B 2476 | F7000019735C61BA 2477 | F7000019825219B6 2478 | F700001C60D14AFB 2479 | F700001E0405FD38 2480 | F7000020DFBD83D6 2481 | F80000080A44CE0C 2482 | F800000F31A48EEE 2483 | F80000155D1DB637 2484 | F800001F915449F5 2485 | F8000024AC6CC58C 2486 | F800002673C10ABF 2487 | F800002AD266F37C 2488 | F800002AF12E1117 2489 | F800002CEE99B17B 2490 | F8000031F799470E 2491 | F90000003F38EEDA 2492 | F9000001C3E928D6 2493 | F90000040E8F6B99 2494 | F900000411E12E90 2495 | F9000004AD903D62 2496 | F9000008D2B12130 2497 | F9000012D4B15347 2498 | F9000013F332713C 2499 | F90000148CA0857A 2500 | F900001C51BE1798 2501 | FA000002E49C19C8 2502 | FA0000081E3A0BB6 2503 | FA00000B01FB960E 2504 | FA00000B5B20D952 2505 | FA000017B75B8EC2 2506 | FA00001D615CC36E 2507 | FA00001E0BD2E268 2508 | FA00001EEF5E01AF 2509 | FA000020DC7ABBDD 2510 | FA000021FF95263B 2511 | FB00000729260CED 2512 | FB00000C772CBC9A 2513 | FB00000F95D29521 2514 | FB00000FCE3CFCEC 2515 | FB0000164C4940AB 2516 | FB00001A2B213CC4 2517 | FB00001C95FED0A7 2518 | FB0000204C5A21E5 2519 | FB00002101079226 2520 | FB00003A26E70511 2521 | FC00000274C1858F 2522 | FC00000A59ADA5B6 2523 | FC00000BBC382C6B 2524 | FC00000C6CEE0C14 2525 | FC00000E2E80D814 2526 | FC000011D58FF4AB 2527 | FC000015236D4214 2528 | FC000015DD2EDE05 2529 | FC00001C785953AB 2530 | FC00001DF4501038 2531 | FD0000018BE1492A 2532 | FD00000266CE31A4 2533 | FD00000926A0DC8D 2534 | FD00000AF685EDFA 2535 | FD00000F06A8DF52 2536 | FD000011395E3B45 2537 | FD000018EB2210FF 2538 | FD00001B24DA383B 2539 | FD00001B3599A583 2540 | FD00001B42248CCF 2541 | FE000003E296CCC7 2542 | FE000005DFF04DE8 2543 | FE00000717108007 2544 | FE00000860CF2337 2545 | FE00000A2A5DAA49 2546 | FE00000A3A9726CB 2547 | FE00000E927D102B 2548 | FE00000F85FADC18 2549 | FE000013B28E1C00 2550 | FE00001E71B0371E 2551 | FF000005B7AEC203 2552 | FF0000063F84B870 2553 | FF0000067A45E214 2554 | FF000009157EFE38 2555 | FF00000BB7C06BDC 2556 | FF0000103CABBA71 2557 | FF000012BA413437 2558 | FF000013EB45E39C 2559 | FF00001537498379 2560 | FF0000183E7C5602 2561 | --------------------------------------------------------------------------------