root/usr/src/cmd/hal/addons/network-devices/cache.c
/*
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 *
 * Licensed under the Academic Free License version 2.1
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include <libhal.h>
#include <logger.h>

#include <glib.h>

#include "network-discovery.h"

/*
 * The interfaces in this file comprise a means of keeping track of devices
 * that we have already seen and those that have gone missing.  This allows
 * us to quickly determine if we need to probe the device and quickly search
 * for devices that are no longer available.
 */

typedef struct {
        LibHalContext *ctx;
        time_t timestamp;
} removal_args_t;

static GHashTable *seen = NULL;

static gboolean
device_remove_if_stale(gpointer key, gpointer value, gpointer user_data)
{
        gboolean result = FALSE;
        removal_args_t *args = user_data;
        char *name = key;
        time_t *val = value;

        HAL_DEBUG(("test stale: %s (%d > %d)", name, args->timestamp, *val));
        if (args->timestamp > *val) {
                DBusError error;
                char **udi = NULL;
                int num = 0;

                dbus_error_init(&error);
                udi = libhal_manager_find_device_string_match(args->ctx,
                                        "network_device.address", name,
                                        &num, &error);

                if (udi != NULL) {
                        int i;

                        for (i = 0; i < num; i++) {
                                libhal_remove_device(args->ctx, udi[i], &error);
                                HAL_DEBUG(("remove: %s (%s)", name, udi[i]));
                        }
                        libhal_free_string_array(udi);
                        result = TRUE;
                }
                if (dbus_error_is_set(&error))
                        dbus_error_free(&error);
        }

        return (result);
}

void
scan_for_stale_devices(LibHalContext *ctx, time_t timestamp)
{
        if (seen != NULL) {
                removal_args_t args[1];

                args->ctx = ctx;
                args->timestamp = timestamp;

                g_hash_table_foreach_remove(seen, device_remove_if_stale, args);
        }
}

gboolean
device_seen(char *name)
{
        gboolean result;
        char *key;
        time_t *val;

        if (seen == NULL)
                seen = g_hash_table_new_full(g_str_hash, g_str_equal,
                                                free, free);

        result = g_hash_table_lookup_extended(seen, name,
                                (gpointer)&key, (gpointer)&val);

        if ((result == FALSE) && ((val = calloc(1, sizeof (*val))) != NULL)) {
                g_hash_table_insert(seen, strdup(name), val);
        }
        (void) time(val);
        HAL_DEBUG(("seen: %s (%d)", name, *val));

        return (result);
}