From 0ef82e266d4bfe3d09f0cf65038a2847c69a32e2 Mon Sep 17 00:00:00 2001 From: Radkesvat <134321679+radkesvat@users.noreply.github.com> Date: Thu, 15 Aug 2024 23:51:14 +0000 Subject: [PATCH] reformat / v1.31 --- tunnels/layer3/receiver/receiver.c | 2 +- tunnels/layer3/sender/sender.c | 6 +- .../layer3/tcp_manipulator/tcp_manipulator.c | 2 - ww/CMakeLists.txt | 1 - ww/buffer_pool.c | 2 + ww/config_file.c | 2 + ww/context_queue.c | 1 + ww/idle_table.c | 3 + ww/managers/socket_manager.c | 2 + ww/node.h | 2 + ww/tunnel.h | 9 +- ww/utils/btree.c | 1470 ----------------- ww/utils/btree.h | 156 -- ww/utils/mathutils.h | 7 + ww/utils/sockutils.h | 1 + 15 files changed, 27 insertions(+), 1639 deletions(-) delete mode 100644 ww/utils/btree.c delete mode 100644 ww/utils/btree.h diff --git a/tunnels/layer3/receiver/receiver.c b/tunnels/layer3/receiver/receiver.c index fbe80869..489901cf 100644 --- a/tunnels/layer3/receiver/receiver.c +++ b/tunnels/layer3/receiver/receiver.c @@ -28,7 +28,7 @@ enum mode_dynamic_value_status kDvsSourceMode = kDvsFirstOption, kDvsDestMode }; -struct ip6_hdr; + static void upStream(tunnel_t *self, context_t *c) { diff --git a/tunnels/layer3/sender/sender.c b/tunnels/layer3/sender/sender.c index 3973245e..c7c67977 100644 --- a/tunnels/layer3/sender/sender.c +++ b/tunnels/layer3/sender/sender.c @@ -66,7 +66,6 @@ static void printSendingIPPacketInfo(const unsigned char *buffer, unsigned int l LOGD(logbuf); } - static void upStream(tunnel_t *self, context_t *c) { layer3_senderstate_t *state = TSTATE(self); @@ -88,7 +87,7 @@ static void upStream(tunnel_t *self, context_t *c) if (packet->ip4_header.protocol == 6) { struct tcpheader *tcp_header = (struct tcpheader *) (rawBufMut(c->payload) + ip_header_len); - tcpCheckSum4(&(packet->ip4_header),tcp_header); + tcpCheckSum4(&(packet->ip4_header), tcp_header); } } else if (packet->ip6_header.version == 6) @@ -98,7 +97,7 @@ static void upStream(tunnel_t *self, context_t *c) if (packet->ip6_header.nexthdr == 6) { struct tcpheader *tcp_header = (struct tcpheader *) (rawBufMut(c->payload) + ip_header_len); - tcpCheckSum6(&(packet->ip6_header),tcp_header); + tcpCheckSum6(&(packet->ip6_header), tcp_header); } } else @@ -107,7 +106,6 @@ static void upStream(tunnel_t *self, context_t *c) exit(1); } - state->tun_device_tunnel->upStream(state->tun_device_tunnel, c); } diff --git a/tunnels/layer3/tcp_manipulator/tcp_manipulator.c b/tunnels/layer3/tcp_manipulator/tcp_manipulator.c index 6d61b012..7338b3dc 100644 --- a/tunnels/layer3/tcp_manipulator/tcp_manipulator.c +++ b/tunnels/layer3/tcp_manipulator/tcp_manipulator.c @@ -105,8 +105,6 @@ static void upStream(tunnel_t *self, context_t *c) handleResetBitAction(tcp_header, &(state->reset_bit_action)); - // reCalculateCheckSum(tcp_header, transport_palyoad_len); - self->up->upStream(self->up, c); } diff --git a/ww/CMakeLists.txt b/ww/CMakeLists.txt index 8e9ebe52..83f6f9d1 100644 --- a/ww/CMakeLists.txt +++ b/ww/CMakeLists.txt @@ -18,7 +18,6 @@ add_library(ww STATIC frand.c pipe_line.c utils/utils.c - utils/btree.c managers/signal_manager.c managers/socket_manager.c managers/node_manager.c diff --git a/ww/buffer_pool.c b/ww/buffer_pool.c index 711e7ad7..f0f9d9b1 100644 --- a/ww/buffer_pool.c +++ b/ww/buffer_pool.c @@ -48,6 +48,7 @@ unsigned int getBufferPoolLargeBufferDefaultSize(void) { return LARGE_BUFFER_SIZE; } + unsigned int getBufferPoolSmallBufferDefaultSize(void) { return SMALL_BUFFER_SIZE; @@ -197,6 +198,7 @@ shift_buffer_t *popSmallBuffer(buffer_pool_t *pool) void reuseBuffer(buffer_pool_t *pool, shift_buffer_t *b) { + #if defined(DEBUG) && defined(BYPASS_BUFFERPOOL) destroyShiftBuffer(pool->shift_buffer_pool,b); return; diff --git a/ww/config_file.c b/ww/config_file.c index 194bc744..497880b5 100644 --- a/ww/config_file.c +++ b/ww/config_file.c @@ -34,10 +34,12 @@ void acquireUpdateLock(config_file_t *state) { hmutex_lock(&(state->guard)); } + void releaseUpdateLock(config_file_t *state) { hmutex_unlock(&(state->guard)); } + // only use if you acquired lock before void unsafeCommitChanges(config_file_t *state) { diff --git a/ww/context_queue.c b/ww/context_queue.c index e8845af8..6af71882 100644 --- a/ww/context_queue.c +++ b/ww/context_queue.c @@ -50,6 +50,7 @@ context_t *contextQueuePop(context_queue_t *self) context_t *context = queue_pull_front(&self->q); return context; } + size_t contextQueueLen(context_queue_t *self) { return queue_size(&self->q); diff --git a/ww/idle_table.c b/ww/idle_table.c index a044d5dd..93f5e1df 100644 --- a/ww/idle_table.c +++ b/ww/idle_table.c @@ -28,6 +28,7 @@ struct idle_table_s hhybridmutex_t mutex; uint64_t last_update_ms; uintptr_t memptr; + } ATTR_ALIGNED_LINE_CACHE; void idleCallBack(htimer_t *timer); @@ -92,6 +93,7 @@ idle_item_t *newIdleItem(idle_table_t *self, hash_t key, void *userdata, ExpireC hhybridmutex_unlock(&(self->mutex)); return item; } + void keepIdleItemForAtleast(idle_table_t *self, idle_item_t *item, uint64_t age_ms) { if (item->removed) @@ -104,6 +106,7 @@ void keepIdleItemForAtleast(idle_table_t *self, idle_item_t *item, uint64_t age_ heapq_idles_t_make_heap(&self->hqueue); hhybridmutex_unlock(&(self->mutex)); } + idle_item_t *getIdleItemByHash(tid_t tid, idle_table_t *self, hash_t key) { hhybridmutex_lock(&(self->mutex)); diff --git a/ww/managers/socket_manager.c b/ww/managers/socket_manager.c index 5dba870e..e89cad21 100644 --- a/ww/managers/socket_manager.c +++ b/ww/managers/socket_manager.c @@ -344,6 +344,7 @@ static inline void incrementDistributeTid(void) state->last_round_tid = 0; } } + static void distributeSocket(void *io, socket_filter_t *filter, uint16_t local_port) { @@ -653,6 +654,7 @@ static void listenTcpSinglePort(hloop_t *loop, socket_filter_t *filter, char *ho } filter->v6_dualstack = hio_localaddr(filter->listen_io)->sa_family == AF_INET6; } + static void listenTcp(hloop_t *loop, uint8_t *ports_overlapped) { for (int ri = (kFilterLevels - 1); ri >= 0; ri--) diff --git a/ww/node.h b/ww/node.h index 18816c81..a813a602 100644 --- a/ww/node.h +++ b/ww/node.h @@ -19,6 +19,7 @@ enum node_flags // this node can be a chain head (begin of the chain) kNodeFlagChainHead = (1 << 1) }; + typedef struct tunnel_metadata_s { int32_t version; @@ -43,4 +44,5 @@ typedef struct node_s tunnel_metadata_t metadata; uint32_t refrenced; bool route_starter; + } node_t; diff --git a/ww/tunnel.h b/ww/tunnel.h index 45e6f879..a14cad45 100644 --- a/ww/tunnel.h +++ b/ww/tunnel.h @@ -124,8 +124,6 @@ typedef struct line_s and it can contain a payload buffer, or be just a flag context - the only flag that also has a payload is `first` , other flags have no payload - */ typedef struct context_s { @@ -408,9 +406,10 @@ static inline buffer_pool_t *getContextBufferPool(const context_t *const c) return getWorkerBufferPool(c->line->tid); } -// same as c->payload = NULL, this is necessary before destroying a context to prevent bugs, dose nothing on release -// build - +/* + same as c->payload = NULL, this is necessary before destroying a context to prevent bugs, dose nothing on release + build +*/ static inline void dropContexPayload(context_t *const c) { #if defined(RELEASE) diff --git a/ww/utils/btree.c b/ww/utils/btree.c deleted file mode 100644 index 52dd5419..00000000 --- a/ww/utils/btree.c +++ /dev/null @@ -1,1470 +0,0 @@ -/** -Author & Copyright (C) 2017 Johannes Bernhard Steffens. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#include -#include -#include - -#include "btree.h" - -/**********************************************************************************************************************/ -/// error messages - -static void ext_err( const char* func, const char* file, int line, const char* format, ... ) -{ - fprintf( stderr, "error in function %s (%s:%i):\n", func, file, line ); - va_list args; - va_start( args, format ); - vfprintf( stderr, format, args ); - va_end( args ); - fprintf( stderr, "\n" ); - abort(); -} - -#define ERR( ... ) ext_err( __func__, __FILE__, __LINE__, __VA_ARGS__ ) - -/**********************************************************************************************************************/ -/**********************************************************************************************************************/ -/// btree_ps -/**********************************************************************************************************************/ -/**********************************************************************************************************************/ - -typedef struct -{ - btree_ps_key_t key; - btree_ps_val_t val; -} btree_ps_kv_s; - -static void btree_ps_kv_s_init( btree_ps_kv_s* o ) -{ - o->key = 0; - o->val = 0; -} - -/**********************************************************************************************************************/ - -/** Node of a 2-3 btree. - * Child pointers can have one of three states: - * NULL: corresponding key-value pair is not used (for normal nodes this state only applies to child2) - * BNUL_PS: node is a leaf - * else: node has children - */ -typedef struct btree_node_ps_s -{ - btree_ps_kv_s kv1; - btree_ps_kv_s kv2; - struct btree_node_ps_s* parent; - struct btree_node_ps_s* child0; - struct btree_node_ps_s* child1; - struct btree_node_ps_s* child2; -} btree_node_ps_s; - -// --------------------------------------------------------------------------------------------------------------------- - -/// children of leaf-nodes point to btree_node_ps_s_null -btree_node_ps_s btree_node_ps_s_null_g = { { 0, 0 }, { 0, 0 }, NULL, NULL, NULL, NULL }; -#define BNUL_PS ( &btree_node_ps_s_null_g ) - -// --------------------------------------------------------------------------------------------------------------------- - -static void btree_node_ps_s_init( btree_node_ps_s* o ) -{ - btree_ps_kv_s_init( &o->kv1 ); - btree_ps_kv_s_init( &o->kv2 ); - o->parent = o->child0 = o->child1 = o->child2 = NULL; -} - -// --------------------------------------------------------------------------------------------------------------------- - -static btree_node_ps_s* btree_node_ps_s_find( btree_node_ps_s* root, btree_ps_key_t key ) -{ - if( !root ) return NULL; - btree_node_ps_s* node = NULL; - while( root->child0 != BNUL_PS && root != node ) - { - node = root; - root = ( key < node->kv1.key ) ? node->child0 : - ( !node->child2 && key > node->kv1.key ) ? node->child1 : - ( node->child2 && key > node->kv2.key ) ? node->child2 : - ( node->child2 && key > node->kv1.key && key < node->kv2.key ) ? node->child1 : node; - } - return root; -} - -// --------------------------------------------------------------------------------------------------------------------- - -static void btree_node_ps_s_run( const btree_node_ps_s* root, void(*func)( void* arg, btree_ps_key_t key, btree_ps_val_t val ), void* arg ) -{ - if( !root ) return; - if( !func ) return; - if( root->child0 ) - { - if( root->child0 != BNUL_PS ) btree_node_ps_s_run( root->child0, func, arg ); - } - if( root->child1 ) - { - func( arg, root->kv1.key, root->kv1.val ); - if( root->child1 != BNUL_PS ) btree_node_ps_s_run( root->child1, func, arg ); - } - if( root->child2 ) - { - func( arg, root->kv2.key, root->kv2.val ); - if( root->child2 != BNUL_PS ) btree_node_ps_s_run( root->child2, func, arg ); - } -} - -// --------------------------------------------------------------------------------------------------------------------- - -static size_t btree_node_ps_s_count( const btree_node_ps_s* root, bool (*func)( void* arg, btree_ps_key_t key, btree_ps_val_t val ), void* arg ) -{ - size_t count = 0; - if( !root ) return count; - if( root->child0 ) - { - if( root->child0 != BNUL_PS ) count += btree_node_ps_s_count( root->child0, func, arg ); - } - if( root->child1 ) - { - count += ( func ) ? func( arg, root->kv1.key, root->kv1.val ) : 1; - if( root->child1 != BNUL_PS ) count += btree_node_ps_s_count( root->child1, func, arg ); - } - if( root->child2 ) - { - count += ( func ) ? func( arg, root->kv2.key, root->kv2.val ) : 1; - if( root->child2 != BNUL_PS ) count += btree_node_ps_s_count( root->child2, func, arg ); - } - return count; -} - -// --------------------------------------------------------------------------------------------------------------------- - -static size_t btree_node_ps_s_sum( const btree_node_ps_s* root, bool (*func)( void* arg, btree_ps_key_t key, btree_ps_val_t val ), void* arg ) -{ - size_t sum = 0; - if( !root ) return sum; - if( root->child0 ) - { - if( root->child0 != BNUL_PS ) sum += btree_node_ps_s_sum( root->child0, func, arg ); - } - if( root->child1 ) - { - sum += root->kv1.val * ( ( func ) ? func( arg, root->kv1.key, root->kv1.val ) : 1 ); - if( root->child1 != BNUL_PS ) sum += btree_node_ps_s_sum( root->child1, func, arg ); - } - if( root->child2 ) - { - sum += root->kv2.val * ( ( func ) ? func( arg, root->kv2.key, root->kv2.val ) : 1 ); - if( root->child2 != BNUL_PS ) sum += btree_node_ps_s_sum( root->child2, func, arg ); - } - return sum; -} - -// --------------------------------------------------------------------------------------------------------------------- - -static size_t btree_node_ps_s_keys( btree_node_ps_s* root ) -{ - if( !root || root == BNUL_PS ) return 0; - size_t keys = root->child2 ? 2 : 1; - keys += btree_node_ps_s_keys( root->child0 ); - keys += btree_node_ps_s_keys( root->child1 ); - if( root->child2 ) keys += btree_node_ps_s_keys( root->child2 ); - return keys; -} - -// --------------------------------------------------------------------------------------------------------------------- - -static size_t btree_node_ps_s_depth( btree_node_ps_s* root ) -{ - if( !root || root == BNUL_PS ) return 0; - return 1 + btree_node_ps_s_depth( root->child0 ); -} - -// --------------------------------------------------------------------------------------------------------------------- - -static void btree_node_ps_s_set_parent_child0( btree_node_ps_s* o ) { if( o->child0 && o->child0 != BNUL_PS ) o->child0->parent = o; } -static void btree_node_ps_s_set_parent_child1( btree_node_ps_s* o ) { if( o->child1 && o->child1 != BNUL_PS ) o->child1->parent = o; } -static void btree_node_ps_s_set_parent_child2( btree_node_ps_s* o ) { if( o->child2 && o->child2 != BNUL_PS ) o->child2->parent = o; } -static int btree_node_ps_s_is_leaf( btree_node_ps_s* o ) { return o->child0 == BNUL_PS; } -static int btree_node_ps_s_is_full( btree_node_ps_s* o ) { return o->child2 != NULL; } -static int btree_node_ps_s_is_empty( btree_node_ps_s* o ) { return o->child1 == NULL; } - -// --------------------------------------------------------------------------------------------------------------------- - -static void btree_node_ps_s_check_consistency( btree_node_ps_s* o ) -{ - if( btree_node_ps_s_null_g.kv1.key != 0 ) ERR( "btree_node_ps_s_null was modified" ); - if( btree_node_ps_s_null_g.kv1.val != 0 ) ERR( "btree_node_ps_s_null was modified" ); - if( btree_node_ps_s_null_g.kv2.key != 0 ) ERR( "btree_node_ps_s_null was modified" ); - if( btree_node_ps_s_null_g.kv2.val != 0 ) ERR( "btree_node_ps_s_null was modified" ); - if( btree_node_ps_s_null_g.parent != NULL ) ERR( "btree_node_ps_s_null was modified" ); - if( btree_node_ps_s_null_g.child0 != NULL ) ERR( "btree_node_ps_s_null was modified" ); - if( btree_node_ps_s_null_g.child1 != NULL ) ERR( "btree_node_ps_s_null was modified" ); - if( btree_node_ps_s_null_g.child2 != NULL ) ERR( "btree_node_ps_s_null was modified" ); - - if( !o ) return; - if( btree_node_ps_s_is_empty( o ) ) ERR( "empty node" ); - if( o->child0 == NULL ) ERR( "deleted leaf" ); - if( o->child1 && o->child1 != BNUL_PS ) - { - if( o != o->child0->parent ) ERR( "child0 incorrect parent" ); - if( o != o->child1->parent ) ERR( "child1 incorrect parent" ); - btree_node_ps_s_check_consistency( o->child0 ); - btree_node_ps_s_check_consistency( o->child1 ); - if( o->kv1.key <= o->child0->kv1.key ) ERR( "(%zu <= %zu)", o->kv1.key, o->child0->kv1.key ); - if( o->child0->child2 && o->kv1.key <= o->child0->kv2.key ) ERR( "(%zu <= %zu)", o->kv1.key, o->child0->kv2.key ); - if( o->kv1.key >= o->child1->kv1.key ) ERR( "(%zu >= %zu)", o->kv1.key, o->child1->kv1.key ); - if( o->child1->child2 && o->kv1.key >= o->child1->kv2.key ) ERR( "(%zu >= %zu)", o->kv1.key, o->child1->kv2.key ); - } - if( o->child2 && o->child2 != BNUL_PS ) - { - if( o->kv1.key >= o->kv2.key ) ERR( "(%zu >= %zu)", o->kv1.key, o->kv2.key ); - if( o != o->child2->parent ) ERR( "child2 incorrect parent" ); - btree_node_ps_s_check_consistency( o->child2 ); - if( o->kv2.key <= o->child1->kv1.key ) ERR( "(%zu <= %zu)", o->kv2.key, o->child1->kv1.key ); - if( o->child1->child2 && o->kv2.key <= o->child1->kv2.key ) ERR( "(%zu <= %zu)", o->kv2.key, o->child1->kv2.key ); - if( o->kv2.key >= o->child2->kv1.key ) ERR( "(%zu >= %zu)", o->kv2.key, o->child2->kv1.key ); - if( o->child2->child2 && o->kv2.key >= o->child2->kv2.key ) ERR( "(%zu >= %zu)", o->kv2.key, o->child2->kv2.key ); - } -} - -// --------------------------------------------------------------------------------------------------------------------- - -/**********************************************************************************************************************/ - -// --------------------------------------------------------------------------------------------------------------------- - -struct btree_ps_s -{ - btree_node_ps_s* root; - btree_node_ps_s* chain_beg; // begin of chain of blocks of btree_node_ps_s[] with last element being pointer to next block - btree_node_ps_s* chain_end; // end of chain of blocks - btree_node_ps_s* chain_ins; // pointer for new insertions - btree_node_ps_s* del_chain; // chain of deleted elements (preferably used by new insertions) - void* (*alloc)( void*, size_t size ); // alloc function - size_t block_size; -}; - -// --------------------------------------------------------------------------------------------------------------------- - -btree_ps_s* btree_ps_s_create( void* (*alloc)( void*, size_t size ) ) -{ - btree_ps_s* o = NULL; - if( alloc ) - { - o = alloc( NULL, sizeof( btree_ps_s ) ); - o->alloc = alloc; - } - else - { - o = alloc( NULL, sizeof( btree_ps_s ) ); - o->alloc = alloc; - } - o->root = NULL; - o->chain_beg = NULL; - o->chain_end = NULL; - o->chain_ins = NULL; - o->del_chain = NULL; - o->block_size = 1024; - return o; -} - -// --------------------------------------------------------------------------------------------------------------------- - -void btree_ps_s_discard( btree_ps_s* o ) -{ - o->root = NULL; - - btree_node_ps_s* chain_beg = o->chain_beg; - while( chain_beg ) - { - btree_node_ps_s* new_beg = *( btree_node_ps_s** )( chain_beg + o->block_size ); - o->alloc( chain_beg, 0 ); - chain_beg = new_beg; - } - - o->alloc( o, 0 ); -} - -// --------------------------------------------------------------------------------------------------------------------- - -static btree_node_ps_s* btree_ps_s_new_node( btree_ps_s* o ) -{ - if( o->del_chain ) - { - btree_node_ps_s* new_node = o->del_chain; - o->del_chain = new_node->parent; - btree_node_ps_s_init( new_node ); - return new_node; - } - else - { - if( o->chain_ins == o->chain_end ) - { - btree_node_ps_s* new_ptr = o->alloc( NULL, o->block_size * sizeof( btree_node_ps_s ) + sizeof( btree_node_ps_s* ) ); - if( !o->chain_beg ) - { - o->chain_beg = new_ptr; - } - else - { - ( ( btree_node_ps_s** )( o->chain_end ) )[ 0 ] = new_ptr; - } - o->chain_ins = new_ptr; - o->chain_end = new_ptr + o->block_size; - *( btree_node_ps_s** )( o->chain_end ) = NULL; - } - btree_node_ps_s* new_node = o->chain_ins; - btree_node_ps_s_init( new_node ); - o->chain_ins++; - return new_node; - } -} - -// --------------------------------------------------------------------------------------------------------------------- - -// Deleted nodes are marked by setting all children NULL -// and chained together using pointer btree_node_ps_s.parent. -static void btree_ps_s_delete_node( btree_ps_s* o, btree_node_ps_s* node ) -{ - node->child0 = NULL; - node->child1 = NULL; - node->child2 = NULL; - node->parent = o->del_chain; - o->del_chain = node; -} - -// --------------------------------------------------------------------------------------------------------------------- - -// recursively pushes an element into the tree -static void btree_ps_s_push( btree_ps_s* o, btree_node_ps_s* node, btree_ps_kv_s* kv, btree_node_ps_s* child0, btree_node_ps_s* child1 ) -{ - if( btree_node_ps_s_is_full( node ) ) - { - btree_node_ps_s* l_node = node; - btree_node_ps_s* r_node = btree_ps_s_new_node( o ); - btree_ps_kv_s root_kv; - - if( kv->key < node->kv1.key ) - { - root_kv = l_node->kv1; - r_node->kv1 = l_node->kv2; - r_node->child0 = l_node->child1; - r_node->child1 = l_node->child2; - l_node->kv1 = *kv; - l_node->child0 = child0; - l_node->child1 = child1; - } - else if( kv->key > node->kv2.key ) - { - root_kv = l_node->kv2; - r_node->kv1 = *kv; - r_node->child0 = child0; - r_node->child1 = child1; - } - else - { - root_kv = *kv; - r_node->kv1 = l_node->kv2; - r_node->child1 = l_node->child2; - r_node->child0 = child1; - l_node->child1 = child0; - } - r_node->child2 = NULL; - l_node->child2 = NULL; - - btree_node_ps_s_set_parent_child0( r_node ); - btree_node_ps_s_set_parent_child1( r_node ); - btree_node_ps_s_set_parent_child0( l_node ); - btree_node_ps_s_set_parent_child1( l_node ); - - if( l_node->parent ) - { - btree_ps_s_push( o, l_node->parent, &root_kv, l_node, r_node ); - } - else - { - o->root = btree_ps_s_new_node( o ); - o->root->kv1 = root_kv; - o->root->child0 = l_node; - o->root->child1 = r_node; - l_node->parent = o->root; - r_node->parent = o->root; - } - } - else - { - if( kv->key < node->kv1.key ) - { - node->kv2 = node->kv1; - node->kv1 = *kv; - node->child2 = node->child1; - node->child1 = child1; - node->child0 = child0; - btree_node_ps_s_set_parent_child0( node ); - btree_node_ps_s_set_parent_child1( node ); - btree_node_ps_s_set_parent_child2( node ); - } - else - { - node->kv2 = *kv; - node->child2 = child1; - node->child1 = child0; - btree_node_ps_s_set_parent_child1( node ); - btree_node_ps_s_set_parent_child2( node ); - } - } -} - -// --------------------------------------------------------------------------------------------------------------------- - -// Recursively pulls an element from a non-leaf into an empty child node -static void btree_ps_s_pull( btree_ps_s* o, btree_node_ps_s* node ) -{ - if( btree_node_ps_s_is_empty( node->child0 ) ) - { - if( btree_node_ps_s_is_full( node->child1 ) ) - { - node->child0->kv1 = node->kv1; - node->child0->child1 = node->child1->child0; - btree_node_ps_s_set_parent_child1( node->child0 ); - node->kv1 = node->child1->kv1; - node->child1->kv1 = node->child1->kv2; - node->child1->child0 = node->child1->child1; - node->child1->child1 = node->child1->child2; - node->child1->child2 = NULL; - } - else if( btree_node_ps_s_is_full( node ) ) - { - node->child1->kv2 = node->child1->kv1; - node->child1->kv1 = node->kv1; - node->child1->child2 = node->child1->child1; - node->child1->child1 = node->child1->child0; - node->child1->child0 = node->child0->child0; - btree_node_ps_s_set_parent_child0( node->child1 ); - btree_ps_s_delete_node( o, node->child0 ); - node->kv1 = node->kv2; - node->child0 = node->child1; - node->child1 = node->child2; - node->child2 = NULL; - } - else - { - node->child1->kv2 = node->child1->kv1; - node->child1->kv1 = node->kv1; - node->child1->child2 = node->child1->child1; - node->child1->child1 = node->child1->child0; - node->child1->child0 = node->child0->child0; - btree_node_ps_s_set_parent_child0( node->child1 ); - btree_ps_s_delete_node( o, node->child0 ); - node->child0 = node->child1; - node->child1 = node->child2 = NULL; - if( node->parent ) - { - btree_ps_s_pull( o, node->parent ); - } - else - { - o->root = node->child0; - o->root->parent = NULL; - btree_ps_s_delete_node( o, node ); - } - } - } - else if( btree_node_ps_s_is_empty( node->child1 ) ) - { - if( btree_node_ps_s_is_full( node->child0 ) ) - { - node->child1->kv1 = node->kv1; - node->child1->child1 = node->child1->child0; - node->child1->child0 = node->child0->child2; - btree_node_ps_s_set_parent_child0( node->child1 ); - node->kv1 = node->child0->kv2; - node->child0->child2 = NULL; - } - else if( btree_node_ps_s_is_full( node ) ) - { - node->child0->kv2 = node->kv1; - node->child0->child2 = node->child1->child0; - btree_node_ps_s_set_parent_child2( node->child0 ); - btree_ps_s_delete_node( o, node->child1 ); - node->kv1 = node->kv2; - node->child1 = node->child2; - node->child2 = NULL; - } - else - { - node->child0->kv2 = node->kv1; - node->child0->child2 = node->child1->child0; - btree_node_ps_s_set_parent_child2( node->child0 ); - btree_ps_s_delete_node( o, node->child1 ); - node->child1 = node->child2 = NULL; - if( node->parent ) - { - btree_ps_s_pull( o, node->parent ); - } - else - { - o->root = node->child0; - o->root->parent = NULL; - btree_ps_s_delete_node( o, node ); - } - } - } - else // node->child2 is empty - { - if( btree_node_ps_s_is_full( node ) ) - { - if( btree_node_ps_s_is_full( node->child1 ) ) - { - node->child2->kv1 = node->kv2; - node->child2->child1 = node->child2->child0; - node->child2->child0 = node->child1->child2; - btree_node_ps_s_set_parent_child0( node->child2 ); - node->kv2 = node->child1->kv2; - node->child1->child2 = NULL; - } - else - { - node->child1->kv2 = node->kv2; - node->child1->child2 = node->child2->child0; - btree_node_ps_s_set_parent_child2( node->child1 ); - btree_ps_s_delete_node( o, node->child2 ); - node->child2 = NULL; - } - } - } -} - -// --------------------------------------------------------------------------------------------------------------------- - -btree_ps_val_t* btree_ps_s_val( const btree_ps_s* o, btree_ps_key_t key ) -{ - if( !o ) return NULL; - btree_node_ps_s* node = btree_node_ps_s_find( o->root, key ); - if( !node ) return NULL; - if( node->kv1.key == key ) return &node->kv1.val; - if( node->child2 && node->kv2.key == key ) return &node->kv2.val; - return NULL; -} - -// --------------------------------------------------------------------------------------------------------------------- - -int btree_ps_s_set( btree_ps_s* o, btree_ps_key_t key, btree_ps_val_t val ) -{ - if( !o ) return -2; - if( !o->root ) - { - o->root = btree_ps_s_new_node( o ); - o->root->child0 = o->root->child1 = BNUL_PS; - o->root->child2 = NULL; - o->root->kv1.key = key; - o->root->kv1.val = val; - return 1; - } - - btree_node_ps_s* node = btree_node_ps_s_find( o->root, key ); - if( !node ) return -2; - - if( node->kv1.key == key ) - { - if( node->kv1.val == val ) return 0; - node->kv1.val = val; - return -1; - } - else if( node->child2 && node->kv2.key == key ) - { - if( node->kv2.val == val ) return 0; - node->kv2.val = val; - return -1; - } - else - { - btree_ps_kv_s kv = { key, val }; - btree_ps_s_push( o, node, &kv, BNUL_PS, BNUL_PS ); - return 1; - } -} - -// --------------------------------------------------------------------------------------------------------------------- - -int btree_ps_s_remove( btree_ps_s* o, btree_ps_key_t key ) -{ - if( !o ) return -1; - if( !o->root ) return 0; - btree_node_ps_s* node = btree_node_ps_s_find( o->root, key ); - if( !node ) return -1; - - if( node->kv1.key == key ) - { - if( !btree_node_ps_s_is_leaf( node ) ) - { - btree_node_ps_s* trace = node->child0; - while( !btree_node_ps_s_is_leaf( trace ) ) trace = ( trace->child2 ) ? trace->child2 : trace->child1; - if( btree_node_ps_s_is_full( trace ) ) - { - node->kv1 = trace->kv2; - trace->child2 = NULL; - } - else - { - node->kv1 = trace->kv1; - trace->child1 = trace->child2 = NULL; - btree_ps_s_pull( o, trace->parent ); - } - } - else if( btree_node_ps_s_is_full( node ) ) - { - node->kv1 = node->kv2; - node->child2 = NULL; - } - else - { - node->child1 = node->child2 = NULL; - if( node->parent ) - { - btree_ps_s_pull( o, node->parent ); - } - else - { - btree_ps_s_delete_node( o, node ); - o->root = NULL; - } - } - return 1; - } - - if( node->kv2.key == key ) - { - if( !btree_node_ps_s_is_leaf( node ) ) - { - btree_node_ps_s* trace = ( node->child2 ) ? node->child2 : node->child1; - while( !btree_node_ps_s_is_leaf( trace ) ) trace = trace->child0; - if( btree_node_ps_s_is_full( trace ) ) - { - node->kv2 = trace->kv1; - trace->kv1 = trace->kv2; - trace->child2 = NULL; - } - else - { - node->kv2 = trace->kv1; - trace->child1 = trace->child2 = NULL; - btree_ps_s_pull( o, trace->parent ); - } - } - else if( btree_node_ps_s_is_full( node ) ) - { - node->child2 = NULL; - } - else - { - node->child1 = node->child2 = NULL; - if( node->parent ) - { - btree_ps_s_pull( o, node->parent ); - } - else - { - btree_ps_s_delete_node( o, node ); - o->root = NULL; - } - } - return 1; - } - return 0; -} - -// --------------------------------------------------------------------------------------------------------------------- - -void btree_ps_s_run( const btree_ps_s* o, void(*func)( void* arg, btree_ps_key_t key, btree_ps_val_t val ), void* arg ) -{ - btree_node_ps_s_run( o->root, func, arg ); -} - -// --------------------------------------------------------------------------------------------------------------------- - -size_t btree_ps_s_count( const btree_ps_s* o, bool(*func)( void* arg, btree_ps_key_t key, btree_ps_val_t val ), void* arg ) -{ - return btree_node_ps_s_count( o->root, func, arg ); -} - -// --------------------------------------------------------------------------------------------------------------------- - -size_t btree_ps_s_sum( const btree_ps_s* o, bool(*func)( void* arg, btree_ps_key_t key, btree_ps_val_t val ), void* arg ) -{ - return btree_node_ps_s_sum( o->root, func, arg ); -} - -// --------------------------------------------------------------------------------------------------------------------- - -size_t btree_ps_s_depth( const btree_ps_s* o ) -{ - return btree_node_ps_s_depth( o->root ); -} - -// --------------------------------------------------------------------------------------------------------------------- - -static void print_btree_ps_s_status( btree_ps_s* o ) -{ - size_t blocks = 0; - size_t nodes = 0; - size_t deleted_nodes = 0; - if( o->chain_beg ) - { - btree_node_ps_s* chain_beg = o->chain_beg; - while( chain_beg ) - { - chain_beg = *( btree_node_ps_s** )( chain_beg + o->block_size ); - blocks++; - } - nodes = blocks * o->block_size - ( o->chain_end - o->chain_ins ); - } - if( o->del_chain ) - { - btree_node_ps_s* del_chain = o->del_chain; - while( del_chain ) - { - del_chain = del_chain->parent; - deleted_nodes++; - } - } - - size_t used_nodes = nodes - deleted_nodes; - printf( "keys ........... %zu\n", btree_node_ps_s_keys( o->root ) ); - printf( "nodes .......... %zu\n", used_nodes ); - printf( "keys/nodes ..... %5.4f\n", used_nodes > 0 ? ( double )( btree_node_ps_s_keys( o->root ) ) / used_nodes : 0 ); - printf( "depth .......... %zu\n", btree_node_ps_s_depth( o->root ) ); - printf( "block size ..... %zu\n", o->block_size ); - printf( "blocks ......... %zu\n", blocks ); - printf( "deleted nodes .. %zu\n", deleted_nodes ); -} - -// --------------------------------------------------------------------------------------------------------------------- - -/**********************************************************************************************************************/ -/**********************************************************************************************************************/ -/// btree_vd -/**********************************************************************************************************************/ -/**********************************************************************************************************************/ - -// E use the specifier 'kv' in this structure for consistency reasons even though this tree has no dedicated value -typedef struct -{ - btree_vd_key_t key; -} btree_vd_kv_s; - -static void btree_vd_kv_s_init( btree_vd_kv_s* o ) -{ - o->key = 0; -} - -/**********************************************************************************************************************/ - -/** Node of a 2-3 btree. - * Child pointers can have one of three states: - * NULL: corresponding key-value pair is not used (for normal nodes this state only applies to child2) - * BNUL_VP: node is a leaf - * else: node has children - */ -typedef struct btree_node_vd_s -{ - btree_vd_kv_s kv1; - btree_vd_kv_s kv2; - struct btree_node_vd_s* parent; - struct btree_node_vd_s* child0; - struct btree_node_vd_s* child1; - struct btree_node_vd_s* child2; -} btree_node_vd_s; - -/// children of leaf-nodes point to btree_node_vd_s_null -btree_node_vd_s btree_node_vd_s_null_g = { { NULL }, { NULL }, NULL, NULL, NULL, NULL }; -#define BNUL_VP ( &btree_node_vd_s_null_g ) - -// --------------------------------------------------------------------------------------------------------------------- - -static void btree_node_vd_s_init( btree_node_vd_s* o ) -{ - btree_vd_kv_s_init( &o->kv1 ); - btree_vd_kv_s_init( &o->kv2 ); - o->parent = o->child0 = o->child1 = o->child2 = NULL; -} - -// --------------------------------------------------------------------------------------------------------------------- - -static btree_node_vd_s* btree_node_vd_s_find( btree_node_vd_s* root, btree_vd_key_t key ) -{ - if( !root ) return NULL; - btree_node_vd_s* node = NULL; - while( root->child0 != BNUL_VP && root != node ) - { - node = root; - root = ( key < node->kv1.key ) ? node->child0 : - ( !node->child2 && key > node->kv1.key ) ? node->child1 : - ( node->child2 && key > node->kv2.key ) ? node->child2 : - ( node->child2 && key > node->kv1.key && key < node->kv2.key ) ? node->child1 : node; - } - return root; -} - -// --------------------------------------------------------------------------------------------------------------------- - -static btree_vd_key_t btree_node_vd_s_largest_below_equal( btree_node_vd_s* root, btree_vd_key_t key ) -{ - if( !root ) return 0; - if( root->child0 == BNUL_VP ) - { - if( ( root->child2 ) && key >= root->kv2.key ) return root->kv2.key; - return ( key >= root->kv1.key ) ? root->kv1.key : 0; - } - else if( ( root->child2 ) && key >= root->kv2.key ) - { - btree_vd_key_t branch_key = btree_node_vd_s_largest_below_equal( root->child2, key ); - return ( branch_key >= root->kv2.key ) ? branch_key : root->kv2.key; - } - else if( key >= root->kv1.key ) - { - btree_vd_key_t branch_key = btree_node_vd_s_largest_below_equal( root->child1, key ); - return ( branch_key >= root->kv1.key ) ? branch_key : root->kv1.key; - } - else - { - return btree_node_vd_s_largest_below_equal( root->child0, key ); - } -} - -// --------------------------------------------------------------------------------------------------------------------- - -static void btree_node_vd_s_run( const btree_node_vd_s* root, void(*func)( void* arg, btree_vd_key_t key ), void* arg ) -{ - if( !root ) return; - if( !func ) return; - if( root->child0 ) - { - if( root->child0 != BNUL_VP ) btree_node_vd_s_run( root->child0, func, arg ); - } - if( root->child1 ) - { - func( arg, root->kv1.key ); - if( root->child1 != BNUL_VP ) btree_node_vd_s_run( root->child1, func, arg ); - } - if( root->child2 ) - { - func( arg, root->kv2.key ); - if( root->child2 != BNUL_VP ) btree_node_vd_s_run( root->child2, func, arg ); - } -} - -// --------------------------------------------------------------------------------------------------------------------- - -static size_t btree_node_vd_s_count( const btree_node_vd_s* root, bool (*func)( void* arg, btree_vd_key_t key ), void* arg ) -{ - size_t count = 0; - if( !root ) return count; - if( root->child0 ) - { - if( root->child0 != BNUL_VP ) count += btree_node_vd_s_count( root->child0, func, arg ); - } - if( root->child1 ) - { - count += ( func ) ? func( arg, root->kv1.key ) : 1; - if( root->child1 != BNUL_VP ) count += btree_node_vd_s_count( root->child1, func, arg ); - } - if( root->child2 ) - { - count += ( func ) ? func( arg, root->kv2.key ) : 1; - if( root->child2 != BNUL_VP ) count += btree_node_vd_s_count( root->child2, func, arg ); - } - return count; -} - -// --------------------------------------------------------------------------------------------------------------------- - -static size_t btree_node_vd_s_keys( btree_node_vd_s* root ) -{ - if( !root || root == BNUL_VP ) return 0; - size_t keys = root->child2 ? 2 : 1; - keys += btree_node_vd_s_keys( root->child0 ); - keys += btree_node_vd_s_keys( root->child1 ); - if( root->child2 ) keys += btree_node_vd_s_keys( root->child2 ); - return keys; -} - -// --------------------------------------------------------------------------------------------------------------------- - -static size_t btree_node_vd_s_depth( btree_node_vd_s* root ) -{ - if( !root || root == BNUL_VP ) return 0; - return 1 + btree_node_vd_s_depth( root->child0 ); -} - -// --------------------------------------------------------------------------------------------------------------------- - -static void btree_node_vd_s_set_parent_child0( btree_node_vd_s* o ) { if( o->child0 && o->child0 != BNUL_VP ) o->child0->parent = o; } -static void btree_node_vd_s_set_parent_child1( btree_node_vd_s* o ) { if( o->child1 && o->child1 != BNUL_VP ) o->child1->parent = o; } -static void btree_node_vd_s_set_parent_child2( btree_node_vd_s* o ) { if( o->child2 && o->child2 != BNUL_VP ) o->child2->parent = o; } -static int btree_node_vd_s_is_leaf( btree_node_vd_s* o ) { return o->child0 == BNUL_VP; } -static int btree_node_vd_s_is_full( btree_node_vd_s* o ) { return o->child2 != NULL; } -static int btree_node_vd_s_is_empty( btree_node_vd_s* o ) { return o->child1 == NULL; } - -// --------------------------------------------------------------------------------------------------------------------- - -static void btree_node_vd_s_check_consistency( btree_node_vd_s* o ) -{ - if( btree_node_vd_s_null_g.kv1.key != 0 ) ERR( "btree_node_vd_s_null was modified" ); - if( btree_node_vd_s_null_g.kv2.key != 0 ) ERR( "btree_node_vd_s_null was modified" ); - if( btree_node_vd_s_null_g.parent != NULL ) ERR( "btree_node_vd_s_null was modified" ); - if( btree_node_vd_s_null_g.child0 != NULL ) ERR( "btree_node_vd_s_null was modified" ); - if( btree_node_vd_s_null_g.child1 != NULL ) ERR( "btree_node_vd_s_null was modified" ); - if( btree_node_vd_s_null_g.child2 != NULL ) ERR( "btree_node_vd_s_null was modified" ); - - if( !o ) return; - if( btree_node_vd_s_is_empty( o ) ) ERR( "empty node" ); - if( o->child0 == NULL ) ERR( "deleted leaf" ); - if( o->child1 && o->child1 != BNUL_VP ) - { - if( o != o->child0->parent ) ERR( "child0 incorrect parent" ); - if( o != o->child1->parent ) ERR( "child1 incorrect parent" ); - btree_node_vd_s_check_consistency( o->child0 ); - btree_node_vd_s_check_consistency( o->child1 ); - if( o->kv1.key <= o->child0->kv1.key ) ERR( "(%zu <= %zu)", o->kv1.key, o->child0->kv1.key ); - if( o->child0->child2 && o->kv1.key <= o->child0->kv2.key ) ERR( "(%zu <= %zu)", o->kv1.key, o->child0->kv2.key ); - if( o->kv1.key >= o->child1->kv1.key ) ERR( "(%zu >= %zu)", o->kv1.key, o->child1->kv1.key ); - if( o->child1->child2 && o->kv1.key >= o->child1->kv2.key ) ERR( "(%zu >= %zu)", o->kv1.key, o->child1->kv2.key ); - } - if( o->child2 && o->child2 != BNUL_VP ) - { - if( o->kv1.key >= o->kv2.key ) ERR( "(%zu >= %zu)", o->kv1.key, o->kv2.key ); - if( o != o->child2->parent ) ERR( "child2 incorrect parent" ); - btree_node_vd_s_check_consistency( o->child2 ); - if( o->kv2.key <= o->child1->kv1.key ) ERR( "(%zu <= %zu)", o->kv2.key, o->child1->kv1.key ); - if( o->child1->child2 && o->kv2.key <= o->child1->kv2.key ) ERR( "(%zu <= %zu)", o->kv2.key, o->child1->kv2.key ); - if( o->kv2.key >= o->child2->kv1.key ) ERR( "(%zu >= %zu)", o->kv2.key, o->child2->kv1.key ); - if( o->child2->child2 && o->kv2.key >= o->child2->kv2.key ) ERR( "(%zu >= %zu)", o->kv2.key, o->child2->kv2.key ); - } -} - -// --------------------------------------------------------------------------------------------------------------------- - -/**********************************************************************************************************************/ - -// --------------------------------------------------------------------------------------------------------------------- - -struct btree_vd_s -{ - btree_node_vd_s* root; - btree_node_vd_s* chain_beg; // begin of chain of blocks of btree_node_vd_s[] with last element being pointer to next block - btree_node_vd_s* chain_end; // end of chain of blocks - btree_node_vd_s* chain_ins; // pointer for new insertions - btree_node_vd_s* del_chain; // chain of deleted elements (preferably used by new insertions) - void* (*alloc)( void*, size_t size ); // alloc function - size_t block_size; -}; - -// --------------------------------------------------------------------------------------------------------------------- - -btree_vd_s* btree_vd_s_create( void* (*alloc)( void*, size_t size ) ) -{ - btree_vd_s* o = NULL; - - o = alloc( NULL, sizeof( btree_vd_s ) ); - o->alloc = alloc; - - o->root = NULL; - o->chain_beg = NULL; - o->chain_end = NULL; - o->chain_ins = NULL; - o->del_chain = NULL; - o->block_size = 1024; - return o; -} - -// --------------------------------------------------------------------------------------------------------------------- - -void btree_vd_s_discard( btree_vd_s* o ) -{ - o->root = NULL; - - btree_node_vd_s* chain_beg = o->chain_beg; - while( chain_beg ) - { - btree_node_vd_s* new_beg = *( btree_node_vd_s** )( chain_beg + o->block_size ); - o->alloc( chain_beg, 0 ); - chain_beg = new_beg; - } - - o->alloc( o, 0 ); -} - -// --------------------------------------------------------------------------------------------------------------------- - -static btree_node_vd_s* btree_vd_s_new_node( btree_vd_s* o ) -{ - if( o->del_chain ) - { - btree_node_vd_s* new_node = o->del_chain; - o->del_chain = new_node->parent; - btree_node_vd_s_init( new_node ); - return new_node; - } - else - { - if( o->chain_ins == o->chain_end ) - { - btree_node_vd_s* new_ptr = o->alloc( NULL, o->block_size * sizeof( btree_node_vd_s ) + sizeof( btree_node_vd_s* ) ); - if( !o->chain_beg ) - { - o->chain_beg = new_ptr; - } - else - { - ( ( btree_node_vd_s** )( o->chain_end ) )[ 0 ] = new_ptr; - } - o->chain_ins = new_ptr; - o->chain_end = new_ptr + o->block_size; - *( btree_node_vd_s** )( o->chain_end ) = NULL; - } - btree_node_vd_s* new_node = o->chain_ins; - btree_node_vd_s_init( new_node ); - o->chain_ins++; - return new_node; - } -} - -// --------------------------------------------------------------------------------------------------------------------- - -// Deleted nodes are marked by setting all children NULL -// and chained together using pointer btree_node_vd_s.parent. -static void btree_vd_s_delete_node( btree_vd_s* o, btree_node_vd_s* node ) -{ - node->child0 = NULL; - node->child1 = NULL; - node->child2 = NULL; - node->parent = o->del_chain; - o->del_chain = node; -} - -// --------------------------------------------------------------------------------------------------------------------- - -// recursively pushes an element into the tree -static void btree_vd_s_push( btree_vd_s* o, btree_node_vd_s* node, btree_vd_kv_s* kv, btree_node_vd_s* child0, btree_node_vd_s* child1 ) -{ - if( btree_node_vd_s_is_full( node ) ) - { - btree_node_vd_s* l_node = node; - btree_node_vd_s* r_node = btree_vd_s_new_node( o ); - btree_vd_kv_s root_kv; - - if( kv->key < node->kv1.key ) - { - root_kv = l_node->kv1; - r_node->kv1 = l_node->kv2; - r_node->child0 = l_node->child1; - r_node->child1 = l_node->child2; - l_node->kv1 = *kv; - l_node->child0 = child0; - l_node->child1 = child1; - } - else if( kv->key > node->kv2.key ) - { - root_kv = l_node->kv2; - r_node->kv1 = *kv; - r_node->child0 = child0; - r_node->child1 = child1; - } - else - { - root_kv = *kv; - r_node->kv1 = l_node->kv2; - r_node->child1 = l_node->child2; - r_node->child0 = child1; - l_node->child1 = child0; - } - r_node->child2 = NULL; - l_node->child2 = NULL; - - btree_node_vd_s_set_parent_child0( r_node ); - btree_node_vd_s_set_parent_child1( r_node ); - btree_node_vd_s_set_parent_child0( l_node ); - btree_node_vd_s_set_parent_child1( l_node ); - - if( l_node->parent ) - { - btree_vd_s_push( o, l_node->parent, &root_kv, l_node, r_node ); - } - else - { - o->root = btree_vd_s_new_node( o ); - o->root->kv1 = root_kv; - o->root->child0 = l_node; - o->root->child1 = r_node; - l_node->parent = o->root; - r_node->parent = o->root; - } - } - else - { - if( kv->key < node->kv1.key ) - { - node->kv2 = node->kv1; - node->kv1 = *kv; - node->child2 = node->child1; - node->child1 = child1; - node->child0 = child0; - btree_node_vd_s_set_parent_child0( node ); - btree_node_vd_s_set_parent_child1( node ); - btree_node_vd_s_set_parent_child2( node ); - } - else - { - node->kv2 = *kv; - node->child2 = child1; - node->child1 = child0; - btree_node_vd_s_set_parent_child1( node ); - btree_node_vd_s_set_parent_child2( node ); - } - } -} - -// --------------------------------------------------------------------------------------------------------------------- - -// Recursively pulls an element from a non-leaf into an empty child node -static void btree_vd_s_pull( btree_vd_s* o, btree_node_vd_s* node ) -{ - if( btree_node_vd_s_is_empty( node->child0 ) ) - { - if( btree_node_vd_s_is_full( node->child1 ) ) - { - node->child0->kv1 = node->kv1; - node->child0->child1 = node->child1->child0; - btree_node_vd_s_set_parent_child1( node->child0 ); - node->kv1 = node->child1->kv1; - node->child1->kv1 = node->child1->kv2; - node->child1->child0 = node->child1->child1; - node->child1->child1 = node->child1->child2; - node->child1->child2 = NULL; - } - else if( btree_node_vd_s_is_full( node ) ) - { - node->child1->kv2 = node->child1->kv1; - node->child1->kv1 = node->kv1; - node->child1->child2 = node->child1->child1; - node->child1->child1 = node->child1->child0; - node->child1->child0 = node->child0->child0; - btree_node_vd_s_set_parent_child0( node->child1 ); - btree_vd_s_delete_node( o, node->child0 ); - node->kv1 = node->kv2; - node->child0 = node->child1; - node->child1 = node->child2; - node->child2 = NULL; - } - else - { - node->child1->kv2 = node->child1->kv1; - node->child1->kv1 = node->kv1; - node->child1->child2 = node->child1->child1; - node->child1->child1 = node->child1->child0; - node->child1->child0 = node->child0->child0; - btree_node_vd_s_set_parent_child0( node->child1 ); - btree_vd_s_delete_node( o, node->child0 ); - node->child0 = node->child1; - node->child1 = node->child2 = NULL; - if( node->parent ) - { - btree_vd_s_pull( o, node->parent ); - } - else - { - o->root = node->child0; - o->root->parent = NULL; - btree_vd_s_delete_node( o, node ); - } - } - } - else if( btree_node_vd_s_is_empty( node->child1 ) ) - { - if( btree_node_vd_s_is_full( node->child0 ) ) - { - node->child1->kv1 = node->kv1; - node->child1->child1 = node->child1->child0; - node->child1->child0 = node->child0->child2; - btree_node_vd_s_set_parent_child0( node->child1 ); - node->kv1 = node->child0->kv2; - node->child0->child2 = NULL; - } - else if( btree_node_vd_s_is_full( node ) ) - { - node->child0->kv2 = node->kv1; - node->child0->child2 = node->child1->child0; - btree_node_vd_s_set_parent_child2( node->child0 ); - btree_vd_s_delete_node( o, node->child1 ); - node->kv1 = node->kv2; - node->child1 = node->child2; - node->child2 = NULL; - } - else - { - node->child0->kv2 = node->kv1; - node->child0->child2 = node->child1->child0; - btree_node_vd_s_set_parent_child2( node->child0 ); - btree_vd_s_delete_node( o, node->child1 ); - node->child1 = node->child2 = NULL; - if( node->parent ) - { - btree_vd_s_pull( o, node->parent ); - } - else - { - o->root = node->child0; - o->root->parent = NULL; - btree_vd_s_delete_node( o, node ); - } - } - } - else // node->child2 is empty - { - if( btree_node_vd_s_is_full( node ) ) - { - if( btree_node_vd_s_is_full( node->child1 ) ) - { - node->child2->kv1 = node->kv2; - node->child2->child1 = node->child2->child0; - node->child2->child0 = node->child1->child2; - btree_node_vd_s_set_parent_child0( node->child2 ); - node->kv2 = node->child1->kv2; - node->child1->child2 = NULL; - } - else - { - node->child1->kv2 = node->kv2; - node->child1->child2 = node->child2->child0; - btree_node_vd_s_set_parent_child2( node->child1 ); - btree_vd_s_delete_node( o, node->child2 ); - node->child2 = NULL; - } - } - } -} - -// --------------------------------------------------------------------------------------------------------------------- - -bool btree_vd_s_exists( const btree_vd_s* o, btree_vd_key_t key ) -{ - if( !o ) return false; - btree_node_vd_s* node = btree_node_vd_s_find( o->root, key ); - if( !node ) return false; - if( node->kv1.key == key ) return true; - if( node->child2 && node->kv2.key == key ) return true; - return false; -} - -// --------------------------------------------------------------------------------------------------------------------- - -btree_vd_key_t btree_vd_s_largest_below_equal( const btree_vd_s* o, btree_vd_key_t key ) -{ - btree_vd_key_t ret = btree_node_vd_s_largest_below_equal( o->root, key ); - - // for the (hypothetical) case where ( NULL != (vp_t)0 ) - return ( ret == 0 ) ? NULL : ret; -} - -// --------------------------------------------------------------------------------------------------------------------- - -int btree_vd_s_set( btree_vd_s* o, btree_vd_key_t key ) -{ - if( !o ) return -2; - if( !o->root ) - { - o->root = btree_vd_s_new_node( o ); - o->root->child0 = o->root->child1 = BNUL_VP; - o->root->child2 = NULL; - o->root->kv1.key = key; - return 1; - } - - btree_node_vd_s* node = btree_node_vd_s_find( o->root, key ); - if( !node ) return -2; - - if( node->kv1.key == key ) - { - return 0; - } - else if( node->child2 && node->kv2.key == key ) - { - return 0; - } - else - { - btree_vd_kv_s kv = { key }; - btree_vd_s_push( o, node, &kv, BNUL_VP, BNUL_VP ); - return 1; - } -} - -// --------------------------------------------------------------------------------------------------------------------- - -int btree_vd_s_remove( btree_vd_s* o, btree_vd_key_t key ) -{ - if( !o ) return -1; - if( !o->root ) return 0; - btree_node_vd_s* node = btree_node_vd_s_find( o->root, key ); - if( !node ) return -1; - - if( node->kv1.key == key ) - { - if( !btree_node_vd_s_is_leaf( node ) ) - { - btree_node_vd_s* trace = node->child0; - while( !btree_node_vd_s_is_leaf( trace ) ) trace = ( trace->child2 ) ? trace->child2 : trace->child1; - if( btree_node_vd_s_is_full( trace ) ) - { - node->kv1 = trace->kv2; - trace->child2 = NULL; - } - else - { - node->kv1 = trace->kv1; - trace->child1 = trace->child2 = NULL; - btree_vd_s_pull( o, trace->parent ); - } - } - else if( btree_node_vd_s_is_full( node ) ) - { - node->kv1 = node->kv2; - node->child2 = NULL; - } - else - { - node->child1 = node->child2 = NULL; - if( node->parent ) - { - btree_vd_s_pull( o, node->parent ); - } - else - { - btree_vd_s_delete_node( o, node ); - o->root = NULL; - } - } - return 1; - } - - if( node->kv2.key == key ) - { - if( !btree_node_vd_s_is_leaf( node ) ) - { - btree_node_vd_s* trace = ( node->child2 ) ? node->child2 : node->child1; - while( !btree_node_vd_s_is_leaf( trace ) ) trace = trace->child0; - if( btree_node_vd_s_is_full( trace ) ) - { - node->kv2 = trace->kv1; - trace->kv1 = trace->kv2; - trace->child2 = NULL; - } - else - { - node->kv2 = trace->kv1; - trace->child1 = trace->child2 = NULL; - btree_vd_s_pull( o, trace->parent ); - } - } - else if( btree_node_vd_s_is_full( node ) ) - { - node->child2 = NULL; - } - else - { - node->child1 = node->child2 = NULL; - if( node->parent ) - { - btree_vd_s_pull( o, node->parent ); - } - else - { - btree_vd_s_delete_node( o, node ); - o->root = NULL; - } - } - return 1; - } - return 0; -} - -// --------------------------------------------------------------------------------------------------------------------- - -void btree_vd_s_run( const btree_vd_s* o, void(*func)( void* arg, btree_vd_key_t key ), void* arg ) -{ - btree_node_vd_s_run( o->root, func, arg ); -} - -// --------------------------------------------------------------------------------------------------------------------- - -size_t btree_vd_s_count( const btree_vd_s* o, bool(*func)( void* arg, btree_vd_key_t key ), void* arg ) -{ - return btree_node_vd_s_count( o->root, func, arg ); -} - -// --------------------------------------------------------------------------------------------------------------------- - -size_t btree_vd_s_depth( const btree_vd_s* o ) -{ - return btree_node_vd_s_depth( o->root ); -} - -// --------------------------------------------------------------------------------------------------------------------- - -static void print_btree_vd_s_status( btree_vd_s* o ) -{ - size_t blocks = 0; - size_t nodes = 0; - size_t deleted_nodes = 0; - if( o->chain_beg ) - { - btree_node_vd_s* chain_beg = o->chain_beg; - while( chain_beg ) - { - chain_beg = *( btree_node_vd_s** )( chain_beg + o->block_size ); - blocks++; - } - nodes = blocks * o->block_size - ( o->chain_end - o->chain_ins ); - } - if( o->del_chain ) - { - btree_node_vd_s* del_chain = o->del_chain; - while( del_chain ) - { - del_chain = del_chain->parent; - deleted_nodes++; - } - } - - size_t used_nodes = nodes - deleted_nodes; - printf( "keys ........... %zu\n", btree_node_vd_s_keys( o->root ) ); - printf( "nodes .......... %zu\n", used_nodes ); - printf( "keys/nodes ..... %5.4f\n", used_nodes > 0 ? ( double )( btree_node_vd_s_keys( o->root ) ) / used_nodes : 0 ); - printf( "depth .......... %zu\n", btree_node_vd_s_depth( o->root ) ); - printf( "block size ..... %zu\n", o->block_size ); - printf( "blocks ......... %zu\n", blocks ); - printf( "deleted nodes .. %zu\n", deleted_nodes ); -} - -// --------------------------------------------------------------------------------------------------------------------- - diff --git a/ww/utils/btree.h b/ww/utils/btree.h deleted file mode 100644 index af860813..00000000 --- a/ww/utils/btree.h +++ /dev/null @@ -1,156 +0,0 @@ -/** -Author & Copyright (C) 2017 Johannes Bernhard Steffens. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/** btree on the basis of a self-balancing 2-3 tree structure. - * This structure can be used for well-scalable associative data management. - * Worst case complexity is O(log(n)) for access, insertion and deletion. - * - * Internally, this solution uses a node structure with three child pointers, - * one parent pointer and two key-value containers. - * Root-state is indicated by parent==NULL. - * Leaf-state is indicated by child0==BNUL. - * Single-key-state is indicated by child2==NULL. - * Therefore additional state-flags are not needed. - * - * Available btree structures - * - btree_ps: key: void*, value: size_t - * - btree_vd: key: void*, value: no dedicated value -*/ - -#ifndef BTREE_H -#define BTREE_H - -#ifdef __cplusplus - extern "C" { -#endif // __cplusplus - -#include -#include -#include - -/**********************************************************************************************************************/ -/**********************************************************************************************************************/ -// tree of void* as key and size_t as value - -typedef void* btree_ps_key_t; -typedef size_t btree_ps_val_t; - -struct btree_ps_s; -typedef struct btree_ps_s btree_ps_s; - -/// Creates a new btree_ip -btree_ps_s* btree_ps_s_create( void* (*alloc)( void*, size_t size ) ); - -/// Deletes a btree_ip -void btree_ps_s_discard( btree_ps_s* o ); - -/** Returns pointer to the value associated with given key. - * Returns NULL when the key does not exist. - */ -btree_ps_val_t* btree_ps_s_val( const btree_ps_s* o, btree_ps_key_t key ); - -/** Sets a key-value pair in the tree. - * If the key already exists, its value is overwritten. - * Return value: - * 0: key, val already existed -> nothing changed - * 1: key did not exist (key, val) was created - * -1: key already existed but with different value -> value was overwritten - * -2: internal error - */ -int btree_ps_s_set( btree_ps_s* o, btree_ps_key_t key, btree_ps_val_t val ); - -/** Removes a key from the tree. - * Return value: - * 0: key did not exist -> nothing changed - * 1: key found and removed - * -1: internal error - */ -int btree_ps_s_remove( btree_ps_s* o, btree_ps_key_t key ); - -/// calls a function for all tree elements -void btree_ps_s_run( const btree_ps_s* o, void(*func)( void* arg, btree_ps_key_t key, btree_ps_val_t val ), void* arg ); - -/// counts entries for which func returns true; counts all entries in case func is NULL -size_t btree_ps_s_count( const btree_ps_s* o, bool(*func)( void* arg, btree_ps_key_t key, btree_ps_val_t val ), void* arg ); - -/// sums entries for which func returns true; sums all entries in case func is NULL -size_t btree_ps_s_sum( const btree_ps_s* o, bool(*func)( void* arg, btree_ps_key_t key, btree_ps_val_t val ), void* arg ); - -/// return depth of tree -size_t btree_ps_s_depth( const btree_ps_s* o ); - -/**********************************************************************************************************************/ -/**********************************************************************************************************************/ -// tree of void* as key (no dedicated value) - -typedef void* btree_vd_key_t; - -struct btree_vd_s; -typedef struct btree_vd_s btree_vd_s; - -struct btree_vd_s; -typedef struct btree_vd_s btree_vd_s; - -/// Creates a new btree_vd (allows to specify alloc function because this tree type is used in memory management) -btree_vd_s* btree_vd_s_create( void* (*alloc)( void*, size_t size ) ); - -/// Deletes a btree_vd -void btree_vd_s_discard( btree_vd_s* o ); - -/// Checks existence of key -bool btree_vd_s_exists( const btree_vd_s* o, btree_vd_key_t key ); - -/// Returns the largest stored key euqal or below . Returns NULL in case all stored keys are larger than . -btree_vd_key_t btree_vd_s_largest_below_equal( const btree_vd_s* o, btree_vd_key_t key ); - -/** Sets a key in the tree. - * Return value: - * 0: key already existed -> nothing changed - * 1: key did not exist and was created - * -2: internal error - */ -int btree_vd_s_set( btree_vd_s* o, btree_vd_key_t key ); - -/** Removes a key from the tree. - * Return value: - * 0: key did not exist -> nothing changed - * 1: key found and removed - * -1: internal error - */ -int btree_vd_s_remove( btree_vd_s* o, btree_vd_key_t key ); - -/// calls a function for all tree elements -void btree_vd_s_run( const btree_vd_s* o, void(*func)( void* arg, btree_vd_key_t key ), void* arg ); - -/// counts entries for which func returns true; counts all entries in case func is NULL -size_t btree_vd_s_count( const btree_vd_s* o, bool(*func)( void* arg, btree_vd_key_t key ), void* arg ); - -/// return depth of tree -size_t btree_vd_s_depth( const btree_vd_s* o ); - -#ifdef __cplusplus - } -#endif // __cplusplus - -#endif // BTREE_H - - diff --git a/ww/utils/mathutils.h b/ww/utils/mathutils.h index 6417c1e0..755ed114 100644 --- a/ww/utils/mathutils.h +++ b/ww/utils/mathutils.h @@ -132,21 +132,28 @@ static inline long minLong(long a, long b) #else + #ifndef htonll + static inline uint64_t htonll(uint64_t x) { uint32_t low = htonl((uint32_t) (x & 0xFFFFFFFF)); uint32_t high = htonl((uint32_t) (x >> 32)); return ((uint64_t) low << 32) | high; } + #endif + #ifndef ntohll + static inline uint64_t ntohll(uint64_t x) { uint32_t low = ntohl((uint32_t) (x & 0xFFFFFFFF)); uint32_t high = ntohl((uint32_t) (x >> 32)); return ((uint64_t) low << 32) | high; } + #endif + #endif diff --git a/ww/utils/sockutils.h b/ww/utils/sockutils.h index 5960c07a..4fb4db90 100644 --- a/ww/utils/sockutils.h +++ b/ww/utils/sockutils.h @@ -31,6 +31,7 @@ static inline int checkIPRange4(const struct in_addr test_addr, const struct in_ } return 0; } + static inline int checkIPRange6(const struct in6_addr test_addr, const struct in6_addr base_addr, const struct in6_addr subnet_mask) {