#define _GNU_SOURCE /* tdestroy */ #include "registries_items.h" #include "registries.h" #include /* entry registry implemented with a tree */ #include #include #include int delta_counter; int active_counter; /** UNDER NO CIRCUMSTANCE TRY TO USE tfind IT'S BROKEN ( passes the wrong arguments to the comparison function: one of the two is passed already dereferenced) */ /* TSEARCH(3) tree root */ static void *active_registry = NULL; static void *pending_registry = NULL; /* all the is_listed_* functions could be simplified by the use of "tfind" but tfind is broken... (wrong description in manual) */ static int active_entries_compare( const void *pa, const void *pb) { int comparison; active_registry_item *item1 = (active_registry_item*) pa; active_registry_item *item2 = (active_registry_item*) pb; comparison = strcmp( item1->path, item2->path); if ( 0 > comparison) return -1; if ( 0 < comparison) return 1; return 0; } int is_listed_as_active( const char *path){ int found = 0; active_registry_item **tnode; active_registry_item *item = active_registry_item_dummy_new( path); /* not a str, but a pointer to str */ tnode = tsearch( item, &active_registry, active_entries_compare); if( *tnode == item){ tdelete( item, &active_registry, active_entries_compare); found = 0; } else{ found = 1; } active_registry_item_dummy_destroy( item); return found; } static void drain_list_item(void *nodedata){ pending_registry_request *req = (pending_registry_request*) nodedata; if( req->type == INSERT){ add_to_active( req->path); } else{ remove_from_active( req->path); } pending_registry_request_destroy(req); } void update_list_drain_into_active(){ tdestroy( pending_registry, drain_list_item); pending_registry = NULL; } void add_to_active( const char *path){ active_registry_item **tnode; active_registry_item *item = active_registry_item_new( path); tnode = tsearch( item, &active_registry, active_entries_compare); if( *tnode != item){ fprintf( stderr, "inconsistency during insertion of path in active devices list\n"); exit(1); } } void remove_from_active( const char *path){ active_registry_item *dummy_item, **holding_node, *true_item; dummy_item = active_registry_item_dummy_new( path); holding_node = tsearch( dummy_item, &active_registry, active_entries_compare); if(*holding_node == dummy_item){ fprintf( stderr, "inconsistency during removal of path in active devices list\n"); exit(1); } true_item = *holding_node; tdelete( dummy_item, &active_registry, active_entries_compare); active_registry_item_dummy_destroy( dummy_item); active_registry_item_destroy( true_item); } static void active_counting_action( const void *nodep, VISIT which, int depth) { switch ( which) { case preorder: break; case postorder: active_counter++; break; case endorder: break; case leaf: active_counter++; break; } } int active_list_count(){ active_counter = 0; twalk( active_registry, active_counting_action); return active_counter; } static int pending_entries_compare( const void *pa, const void *pb) { pending_registry_request *req1 = ( pending_registry_request*) pa; pending_registry_request *req2 = ( pending_registry_request*) pb; int comparison; comparison = strcmp( req1->path, req2->path); if ( 0 > comparison) return -1; if ( 0 < comparison) return 1; return 0; } /* INTERNAL USE ONLY for querying the presence or absence of entries */ pending_registry_request* get_from_pending_registry( const char *path){ int found = 0; pending_registry_request **tnode; pending_registry_request *req = pending_registry_request_new( path); tnode = tsearch( req, &pending_registry, pending_entries_compare); if( *tnode == req){ tdelete( req, &pending_registry, pending_entries_compare); found = 0; } else{ found = 1; } pending_registry_request_destroy( req); if( ! found){ return NULL; } return *tnode; } int is_listed_for_removal( const char *path){ pending_registry_request *req; req = get_from_pending_registry( path); if( NULL == req){ return 0; } if( req->type == REMOVE){ return 1; } else{ return 0; } } int is_listed_for_insertion( const char *path){ pending_registry_request *req = get_from_pending_registry( path); if( NULL == req){ return 0; } if( req->type == INSERT){ return 1; } else{ return 0; } } void add_to_update_list( const char *path, update_request_type type){ pending_registry_request **tnode; pending_registry_request *req = pending_registry_request_new( path); req->type = type; tnode = tsearch( req, &pending_registry, pending_entries_compare); if( *tnode != req){ pending_registry_request_destroy( req); } } void remove_from_update_list( const char *path){ pending_registry_request **tnode, *found, *req; /*type field is not used in comparison*/ req = pending_registry_request_new( path); /* all this mess just because i can't use tfind */ tnode = tsearch( req, &pending_registry, pending_entries_compare); if( *tnode == req){ printf("inconsistency during removal from update list\n"); exit( 1); } else{ found = *tnode; } tnode = tdelete( found, &pending_registry, pending_entries_compare); pending_registry_request_destroy( req); pending_registry_request_destroy( found); } static void delta_counting_action(const void *nodep, VISIT which, int depth) { pending_registry_request *datap; switch ( which) { case preorder: break; case postorder: datap = *( pending_registry_request**) nodep; if( datap->type == INSERT){ delta_counter++; } else{ delta_counter--; } break; case endorder: break; case leaf: datap = *( pending_registry_request**) nodep; if( datap->type == INSERT){ delta_counter++; } else{ delta_counter--; } break; } } /* each pending insertion counts as +1 each removal counts as -1 */ int update_list_get_delta(){ delta_counter = 0; twalk( pending_registry, delta_counting_action); return delta_counter; } static void active_print(const void *nodep, VISIT which, int depth) { active_registry_item *datap; switch ( which) { case preorder: break; case postorder: datap = *( active_registry_item**) nodep; printf("path : \"%s\" th_id %ld\n", datap->path, datap->thread); break; case endorder: break; case leaf: datap = *( active_registry_item**) nodep; printf("path : \"%s\" th_id %ld\n", datap->path, datap->thread); break; } } static void pending_print(const void *nodep, VISIT which, int depth) { pending_registry_request *datap; switch ( which) { case preorder: break; case postorder: datap = *( pending_registry_request**) nodep; printf("path : \"%s\" code %d\n", datap->path, datap->type); break; case endorder: break; case leaf: datap = *( pending_registry_request**) nodep; printf("path : \"%s\" code %d\n", datap->path, datap->type); break; } } void print_active_list(){ printf(">>>> >>>> print_active_list\n"); twalk( active_registry, active_print); printf("<<<< <<<< print_active_list\n"); } void print_update_list(){ printf(">>>> >>>> print_update_list\n"); twalk( pending_registry, pending_print); printf("<<<< <<<< print_update_list\n"); }