/* * art.h * * This source file is part of the FoundationDB open source project * * Copyright 2013-2020 Apple Inc. and the FoundationDB project authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "fdbclient/FDBTypes.h" #include "flow/Arena.h" #include "flow/Platform.h" #ifndef ART_H #define ART_H struct art_iterator; struct art_tree { enum ART_NODE_TYPE : uint8_t{ ART_LEAF = 0, ART_NODE4 = 1, ART_NODE16 = 2, ART_NODE48 = 3, ART_NODE256 = 4, ART_NODE4_KV = 5, ART_NODE16_KV = 6, ART_NODE48_KV = 7, ART_NODE256_KV = 8 }; #define ART_MIN_LEAF_UNSET 1UL #define ART_LEAF_MATCH_KEY 1 #define ART_LEAF_SMALLER_KEY 2 #define ART_LEAF_LARGER_KEY 3 #define ART_I_FOUND 2 #define ART_I_DEPTH 3 #define ART_I_BACKTRACK 4 #define ART_NEXT 1 #define ART_PREV -1 #define ART_NEITHER 0 //#define ART_IS_LEAF(x) ( (*((ART_NODE_TYPE*)x) == ART_LEAF)) template static inline bool ART_IS_LEAF(T const& x) { return *((ART_NODE_TYPE*)x) == ART_LEAF; } #define ART_LEAF_RAW(x) ((art_leaf*)(x)) #define ART_LEAF_DISPL(x) fat_leaf_offset[(x)->type] #define ART_FAT_NODE_LEAF(node_ptr) (*((art_leaf**) (((char*)(node_ptr))+ART_LEAF_DISPL(node_ptr)))) //In Bytes //This is needed so that we can pre-allocate a static stack to perform efficient backtracking in iterative_bound #define ART_MAX_KEY_LEN 10000 #define _mm_cmpge_epu8(a, b) \ _mm_cmpeq_epi8(_mm_max_epu8(a, b), a) #define _mm_cmple_epu8(a, b) _mm_cmpge_epu8(b, a) #define _mm_cmpgt_epu8(a, b) \ _mm_xor_si128(_mm_cmple_epu8(a, b), _mm_set1_epi8(-1)) #define _mm_cmplt_epu8(a, b) _mm_cmpgt_epu8(b, a) #define ART_MAX_PREFIX_LEN 10 /** * This struct is included as part * of all the various node sizes */ struct art_node { ART_NODE_TYPE type; uint8_t num_children; uint32_t partial_len; unsigned char partial[ART_MAX_PREFIX_LEN]; }; /** * Represents a leaf. These are * of arbitrary size, as they include the key. * Note that the first two fields must be the same as in art_node */ struct art_leaf { ART_NODE_TYPE type; void *value; art_leaf *prev = nullptr; art_leaf *next = nullptr; KeyRef key; art_leaf(const KeyRef &k, void *v) : type(ART_LEAF), value(v), key(k.begin(), k.size()) { } art_leaf(const uint8_t *ptr, int len, void *v) : type(ART_LEAF), value(v), key(ptr, len) {} }; /** * Small node with only 4 children */ struct art_node4 { art_node n; unsigned char keys[4]; art_node *children[4]; }; /** * Node with 16 children */ struct art_node16 { art_node n; unsigned char keys[16]; art_node *children[16]; }; /** * Node with 48 children, but * a full 256 byte field. */ struct art_node48 { art_node n; unsigned char keys[256]; art_node *children[48]; }; /** * Full node with 256 children */ struct art_node256 { art_node n; art_node *children[256]; }; /** * Small node with only 4 children */ struct art_node4_kv { art_node4 n; art_leaf *leaf; }; /** * Node with 16 children */ struct art_node16_kv { art_node16 n; art_leaf *leaf; }; /** * Node with 48 children, but * a full 256 byte field. */ struct art_node48_kv { art_node48 n; art_leaf *leaf; }; /** * Full node with 256 children */ struct art_node256_kv { art_node256 n; art_leaf *leaf; }; private: art_node *root; uint64_t size; Arena *arena; static int fat_leaf_offset[9]; static int node_sizes[9]; static int check_bound_node(art_node *n, const KeyRef &k, int *depth_p, art_leaf **result, bool strict); static int art_bound_leaf(art_node *n, const KeyRef &k, int depth, art_leaf **result); static art_leaf *minimum(art_node *n); static art_leaf *maximum(art_node *n); static int leaf_matches_signed(art_leaf *n, const KeyRef &k, int depth); static int leaf_matches(const art_leaf *n, const KeyRef &k, int depth); static int signed_prefix_mismatch(art_node *n, const KeyRef &k, int depth, art_leaf **min_leaf, bool find_min); static int prefix_mismatch(art_node *n, KeyRef &k, int depth, art_leaf **minout); static art_leaf *minimum_kv(art_node *n); static art_node **find_child(art_node *n, unsigned char c); static void find_next(art_node *n, unsigned char c, art_node **out); static void find_prev(art_node *n, unsigned char c, art_node **out); static int art_next_prev(art_node *n, unsigned char c, art_node **out); void art_bound_iterative(art_node *n, const KeyRef &k, int depth, art_leaf **result, bool strict); static inline int min(int a, int b) { return (a < b) ? a : b; } static inline void *SET_LEAF(void *x) { (*((uint8_t *) x) = 0); return x; } static int check_prefix(const art_node *n, const KeyRef &k, int depth); void recursive_delete_binary(art_node *n, art_node **ref, const KeyRef &k, int depth); void remove_child(art_node *n, art_node **ref, unsigned char c, art_node **l, int depth); //needs this pointer to do allocation art_node *alloc_node(ART_NODE_TYPE type); art_node *alloc_kv_node(ART_NODE_TYPE type); art_leaf *make_leaf(const KeyRef &k, void *value); static void remove_fat_child(art_node *n, art_node **ref, int depth); static void remove_fat_child4(art_node4_kv *n, art_node **ref, int depth); static void remove_child4(art_node4 *n, art_node **ref, art_node **l, int depth); static void remove_fat_child16(art_node16_kv *n, art_node **ref); void remove_child16(art_node16 *n, art_node **ref, art_node **l); static void remove_fat_child48(art_node48_kv *n, art_node **ref); void remove_child48(art_node48 *n, art_node **ref, unsigned char c); static void remove_fat_child256(art_node256_kv *n, art_node **ref); void remove_child256(art_node256 *n, art_node **ref, unsigned char c); static void copy_header(art_node *dest, art_node *src); art_leaf *iterative_insert(art_node *root, art_node **root_ptr, KeyRef &k, void *value, int depth, int *old, int replace_existing); art_leaf *insert_leaf(art_node *n, art_node **ref, const KeyRef &k, void *value, int depth, int *old, int replace_existing); art_leaf *insert_fat_node(art_node *n, art_node **ref, const KeyRef &k, void *value, int depth, int *old, art_leaf *min_of_n, int replace_existing); art_leaf *insert_internal_node(art_node *n, art_node **ref, const KeyRef &k, void *value, int depth, int *old, art_leaf *min_of_n, int prefix_diff, int replace_existing); art_leaf *insert_child(art_node *n, art_node **ref, const KeyRef &k, void *value, int depth, int *old, int replace_existing); static inline int longest_common_prefix(const KeyRef &k1, const KeyRef &k2, int depth); static void insert_after(art_leaf *l_new, art_leaf *l_existing); static void insert_before(art_leaf *l_new, art_leaf *l_existing); void add_child(art_node *n, art_node **ref, unsigned char c, void *child); void add_child256(art_node256 *n, art_node **ref, unsigned char c, void *child); void add_child48(art_node48 *n, art_node **ref, unsigned char c, void *child); void add_child16(art_node16 *n, art_node **ref, unsigned char c, void *child); void add_child4(art_node4 *n, art_node **ref, unsigned char c, void *child); public: art_tree(Arena &a) { this->arena = &a; this->root = alloc_node(ART_NODE4); //Sentinel node. Also needed for empty key this->size = 0; } art_iterator lower_bound(const KeyRef &k); art_iterator upper_bound(const KeyRef &k); art_iterator insert(KeyRef &key, void *value); art_iterator insert_if_absent(KeyRef &key, void *value, int *replaced); void erase(const art_iterator &it); uint64_t count() { return size; } }; //art_tree struct art_iterator { private: art_tree::art_leaf *leaf; public: art_iterator(art_tree::art_leaf *l) { leaf = l; } art_iterator(const art_iterator &i) { leaf = i.leaf; } art_iterator() { leaf = nullptr; } art_iterator &operator++() { leaf = leaf->next; return (*this); } art_iterator &operator--() { leaf = leaf->prev; return (*this); } bool operator==(const art_iterator &other) const { return leaf == other.leaf; } bool operator!=(const art_iterator &other) const { return leaf != other.leaf; } const KeyRef &key() const { return leaf->key; } void *value() const { return leaf->value; } void **value_ptr() { return &(leaf->value); } }; #endif //ART_H