project for a (works on my devices) demo
This commit is contained in:
363
registries.c
Normal file
363
registries.c
Normal file
@@ -0,0 +1,363 @@
|
||||
#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");
|
||||
}
|
||||
Reference in New Issue
Block a user