Files
my_device_handler/registries.c
2026-03-13 16:38:39 +01:00

364 lines
7.2 KiB
C

#define _GNU_SOURCE /* tdestroy */
#include "registries_items.h"
#include "registries.h"
#include <search.h> /* entry registry implemented with a tree */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
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");
}