364 lines
7.2 KiB
C
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");
|
|
}
|