mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-18 21:51:57 +00:00
ddb0dcd2fd
* Increase default maximum size of brtie dictionary to 128m ips pbuilder: use newer cmake on ubuntu trusty * no cmake
461 lines
7.5 KiB
C
461 lines
7.5 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <btrie.h>
|
|
|
|
#define PAGE_SIZE 4096
|
|
|
|
|
|
static btrie_node_t *
|
|
btrie_alloc(btrie_t *tree)
|
|
{
|
|
btrie_node_t *p;
|
|
|
|
if (tree->free) {
|
|
p = tree->free;
|
|
tree->free = tree->free->right;
|
|
return p;
|
|
}
|
|
|
|
if (tree->size < sizeof(btrie_node_t)) {
|
|
tree->start = (char *) calloc(sizeof(char), PAGE_SIZE);
|
|
if (tree->start == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
tree->pools[tree->len++] = tree->start;
|
|
tree->size = PAGE_SIZE;
|
|
}
|
|
|
|
p = (btrie_node_t *) tree->start;
|
|
|
|
tree->start += sizeof(btrie_node_t);
|
|
tree->size -= sizeof(btrie_node_t);
|
|
|
|
return p;
|
|
}
|
|
|
|
|
|
btrie_t *
|
|
btrie_create()
|
|
{
|
|
btrie_t *tree = (btrie_t *) malloc(sizeof(btrie_t));
|
|
if (tree == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
tree->free = NULL;
|
|
tree->start = NULL;
|
|
tree->size = 0;
|
|
memset(tree->pools, 0, sizeof(btrie_t *) * BTRIE_MAX_PAGES);
|
|
tree->len = 0;
|
|
|
|
tree->root = btrie_alloc(tree);
|
|
if (tree->root == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
tree->root->right = NULL;
|
|
tree->root->left = NULL;
|
|
tree->root->parent = NULL;
|
|
tree->root->value = BTRIE_NULL;
|
|
|
|
return tree;
|
|
}
|
|
|
|
static size_t
|
|
subtree_weight(btrie_node_t *node)
|
|
{
|
|
size_t weight = 1;
|
|
if (node->left) {
|
|
weight += subtree_weight(node->left);
|
|
}
|
|
if (node->right) {
|
|
weight += subtree_weight(node->right);
|
|
}
|
|
return weight;
|
|
}
|
|
|
|
size_t
|
|
btrie_count(btrie_t *tree)
|
|
{
|
|
if (tree->root == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
return subtree_weight(tree->root);
|
|
}
|
|
|
|
size_t
|
|
btrie_allocated(btrie_t *tree)
|
|
{
|
|
return tree->len * PAGE_SIZE;
|
|
}
|
|
|
|
|
|
int
|
|
btrie_insert(btrie_t *tree, uint32_t key, uint32_t mask,
|
|
uintptr_t value)
|
|
{
|
|
uint32_t bit;
|
|
btrie_node_t *node, *next;
|
|
|
|
bit = 0x80000000;
|
|
|
|
node = tree->root;
|
|
next = tree->root;
|
|
|
|
while (bit & mask) {
|
|
if (key & bit) {
|
|
next = node->right;
|
|
|
|
} else {
|
|
next = node->left;
|
|
}
|
|
|
|
if (next == NULL) {
|
|
break;
|
|
}
|
|
|
|
bit >>= 1;
|
|
node = next;
|
|
}
|
|
|
|
if (next) {
|
|
if (node->value != BTRIE_NULL) {
|
|
return -1;
|
|
}
|
|
|
|
node->value = value;
|
|
return 0;
|
|
}
|
|
|
|
while (bit & mask) {
|
|
next = btrie_alloc(tree);
|
|
if (next == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
next->right = NULL;
|
|
next->left = NULL;
|
|
next->parent = node;
|
|
next->value = BTRIE_NULL;
|
|
|
|
if (key & bit) {
|
|
node->right = next;
|
|
|
|
} else {
|
|
node->left = next;
|
|
}
|
|
|
|
bit >>= 1;
|
|
node = next;
|
|
}
|
|
|
|
node->value = value;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
btrie_delete(btrie_t *tree, uint32_t key, uint32_t mask)
|
|
{
|
|
uint32_t bit;
|
|
btrie_node_t *node;
|
|
|
|
bit = 0x80000000;
|
|
node = tree->root;
|
|
|
|
while (node && (bit & mask)) {
|
|
if (key & bit) {
|
|
node = node->right;
|
|
|
|
} else {
|
|
node = node->left;
|
|
}
|
|
|
|
bit >>= 1;
|
|
}
|
|
|
|
if (node == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if (node->right || node->left) {
|
|
if (node->value != BTRIE_NULL) {
|
|
node->value = BTRIE_NULL;
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
for ( ;; ) {
|
|
if (node->parent->right == node) {
|
|
node->parent->right = NULL;
|
|
|
|
} else {
|
|
node->parent->left = NULL;
|
|
}
|
|
|
|
node->right = tree->free;
|
|
tree->free = node;
|
|
|
|
node = node->parent;
|
|
|
|
if (node->right || node->left) {
|
|
break;
|
|
}
|
|
|
|
if (node->value != BTRIE_NULL) {
|
|
break;
|
|
}
|
|
|
|
if (node->parent == NULL) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
uintptr_t
|
|
btrie_find(btrie_t *tree, uint32_t key)
|
|
{
|
|
uint32_t bit;
|
|
uintptr_t value;
|
|
btrie_node_t *node;
|
|
|
|
bit = 0x80000000;
|
|
value = BTRIE_NULL;
|
|
node = tree->root;
|
|
|
|
while (node) {
|
|
if (node->value != BTRIE_NULL) {
|
|
value = node->value;
|
|
}
|
|
|
|
if (key & bit) {
|
|
node = node->right;
|
|
|
|
} else {
|
|
node = node->left;
|
|
}
|
|
|
|
bit >>= 1;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
int
|
|
btrie_insert_a6(btrie_t *tree, const uint8_t *key, const uint8_t *mask,
|
|
uintptr_t value)
|
|
{
|
|
uint8_t bit;
|
|
unsigned int i;
|
|
btrie_node_t *node, *next;
|
|
|
|
i = 0;
|
|
bit = 0x80;
|
|
|
|
node = tree->root;
|
|
next = tree->root;
|
|
|
|
while (bit & mask[i]) {
|
|
if (key[i] & bit) {
|
|
next = node->right;
|
|
|
|
} else {
|
|
next = node->left;
|
|
}
|
|
|
|
if (next == NULL) {
|
|
break;
|
|
}
|
|
|
|
bit >>= 1;
|
|
node = next;
|
|
|
|
if (bit == 0) {
|
|
if (++i == 16) {
|
|
break;
|
|
}
|
|
|
|
bit = 0x80;
|
|
}
|
|
}
|
|
|
|
if (next) {
|
|
if (node->value != BTRIE_NULL) {
|
|
return -1;
|
|
}
|
|
|
|
node->value = value;
|
|
return 0;
|
|
}
|
|
|
|
while (bit & mask[i]) {
|
|
next = btrie_alloc(tree);
|
|
if (next == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
next->right = NULL;
|
|
next->left = NULL;
|
|
next->parent = node;
|
|
next->value = BTRIE_NULL;
|
|
|
|
if (key[i] & bit) {
|
|
node->right = next;
|
|
|
|
} else {
|
|
node->left = next;
|
|
}
|
|
|
|
bit >>= 1;
|
|
node = next;
|
|
|
|
if (bit == 0) {
|
|
if (++i == 16) {
|
|
break;
|
|
}
|
|
|
|
bit = 0x80;
|
|
}
|
|
}
|
|
|
|
node->value = value;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
btrie_delete_a6(btrie_t *tree, const uint8_t *key, const uint8_t *mask)
|
|
{
|
|
uint8_t bit;
|
|
unsigned int i;
|
|
btrie_node_t *node;
|
|
|
|
i = 0;
|
|
bit = 0x80;
|
|
node = tree->root;
|
|
|
|
while (node && (bit & mask[i])) {
|
|
if (key[i] & bit) {
|
|
node = node->right;
|
|
|
|
} else {
|
|
node = node->left;
|
|
}
|
|
|
|
bit >>= 1;
|
|
|
|
if (bit == 0) {
|
|
if (++i == 16) {
|
|
break;
|
|
}
|
|
|
|
bit = 0x80;
|
|
}
|
|
}
|
|
|
|
if (node == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if (node->right || node->left) {
|
|
if (node->value != BTRIE_NULL) {
|
|
node->value = BTRIE_NULL;
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
for ( ;; ) {
|
|
if (node->parent->right == node) {
|
|
node->parent->right = NULL;
|
|
|
|
} else {
|
|
node->parent->left = NULL;
|
|
}
|
|
|
|
node->right = tree->free;
|
|
tree->free = node;
|
|
|
|
node = node->parent;
|
|
|
|
if (node->right || node->left) {
|
|
break;
|
|
}
|
|
|
|
if (node->value != BTRIE_NULL) {
|
|
break;
|
|
}
|
|
|
|
if (node->parent == NULL) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
uintptr_t
|
|
btrie_find_a6(btrie_t *tree, const uint8_t *key)
|
|
{
|
|
uint8_t bit;
|
|
uintptr_t value;
|
|
unsigned int i;
|
|
btrie_node_t *node;
|
|
|
|
i = 0;
|
|
bit = 0x80;
|
|
value = BTRIE_NULL;
|
|
node = tree->root;
|
|
|
|
while (node) {
|
|
if (node->value != BTRIE_NULL) {
|
|
value = node->value;
|
|
}
|
|
|
|
if (key[i] & bit) {
|
|
node = node->right;
|
|
|
|
} else {
|
|
node = node->left;
|
|
}
|
|
|
|
bit >>= 1;
|
|
|
|
if (bit == 0) {
|
|
i++;
|
|
bit = 0x80;
|
|
}
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
|
|
int
|
|
btrie_destroy(btrie_t *tree)
|
|
{
|
|
size_t i;
|
|
|
|
|
|
/* free memory pools */
|
|
for (i = 0; i < tree->len; i++) {
|
|
free(tree->pools[i]);
|
|
}
|
|
|
|
free(tree);
|
|
|
|
return 0;
|
|
}
|