/*
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* "Portions Copyright (c) 2003 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License."
*
* @APPLE_LICENSE_HEADER_END@
*/
#include <stdlib.h>
#include "watcher.h"
#include "daemon.h"
list_t *watch_list = NULL;
uint32_t watcher_id = 0;
watcher_t *
watcher_new()
{
watcher_t *w;
list_t *n;
w = (watcher_t *)calloc(1, sizeof(watcher_t));
if (w == NULL) return NULL;
w->wid = ++watcher_id;
w->refcount = 1;
n = _nc_list_new(w);
watch_list = _nc_list_prepend(watch_list, n);
return w;
}
watcher_t *
watcher_retain(watcher_t *w)
{
if (w == NULL) return NULL;
w->refcount++;
return w;
}
void
watcher_release_deferred(watcher_t *w)
{
if (w == NULL) return;
if (w->refcount > 0) w->refcount--;
}
void
watcher_release(watcher_t *w)
{
int i;
if (w == NULL) return;
if (w->refcount > 0) w->refcount--;
if (w->refcount > 0) return;
watch_list = _nc_list_find_release(watch_list, w);
if (w->sub_free != NULL) w->sub_free(w);
if (w->name != NULL)
{
for (i = 0; w->name[i] != NULL; i++) free(w->name[i]);
free(w->name);
}
if (w->fwd != NULL) free(w->fwd);
free(w);
}
void
watcher_add_name(watcher_t *w, const char *name)
{
int i;
if (w == NULL) return;
if (name == NULL) return;
if (w->name == NULL)
{
w->name = (char **)calloc(2, sizeof(char *));
w->name[0] = strdup(name);
return;
}
for (i = 0; w->name[i] != NULL; i++)
{
if (!strcmp(w->name[i], name)) return;
}
w->name = (char **)realloc(w->name, (i + 2) * sizeof(char *));
w->name[i] = strdup(name);
w->name[i + 1] = NULL;
}
void
watcher_remove_name(watcher_t *w, const char *name)
{
int i, j;
if (w == NULL) return;
if (name == NULL) return;
if (w->name == NULL) return;
for (i = 0; w->name[i] != NULL; i++)
{
if (!strcmp(w->name[i], name))
{
free(w->name[i]);
for (j = i + 1; w->name[j] != NULL; j++)
w->name[j - 1] = w->name[j];
w->name[j - 1] = NULL;
w->name = (char **)realloc(w->name, j * sizeof(char *));
return;
}
}
}
static void
watcher_internal_trigger(watcher_t *w, uint32_t t, uint32_t flags, uint32_t level)
{
uint32_t i, postit;
if (w == NULL) return;
if (w->wid != t) return;
#ifdef DEBUG
log_message(LOG_DEBUG, "watcher_trigger %u level %u", t, level);
#endif
postit = 0;
if (w->sub_trigger != NULL) postit = w->sub_trigger(w, flags, level);
if ((w->name != NULL) && (postit != 0))
{
for (i = 0; w->name[i] != NULL; i++) daemon_post(w->name[i], 0, 0);
}
for (i = 0; i < w->count; i++) watcher_trigger(w->fwd[i], 0, level + 1);
}
void
watcher_add_forward(watcher_t *w, uint32_t t)
{
uint32_t i;
if (w == NULL) return;
for (i = 0; i < w->count; i++)
{
if (w->fwd[i] == t) return;
}
if (w->count == 0)
{
w->fwd = (uint32_t *)malloc(sizeof(uint32_t));
}
else
{
w->fwd = (uint32_t *)realloc(w->fwd, (w->count + 1) * sizeof(uint32_t));
}
w->fwd[w->count] = t;
w->count++;
}
void
watcher_remove_forward(watcher_t *w, uint32_t t)
{
uint32_t i, x;
if (w->count == 0) return;
x = w->count + 1;
for (i = 0; i < w->count; i++)
{
if (w->fwd[i] == t)
{
x = i;
break;
}
}
if (x > w->count) return;
if (w->count == 1)
{
free(w->fwd);
w->fwd = NULL;
w->count = 0;
return;
}
for (i = x + 1; i < w->count; i++) w->fwd[i - 1] = w->fwd[i];
w->count--;
w->fwd = (uint32_t *)realloc(w->fwd, w->count * sizeof(uint32_t));
}
void
watcher_trigger(uint32_t t, uint32_t flags, uint32_t level)
{
watcher_t *w;
list_t *n, *x;
for (n = watch_list; n != NULL; n = _nc_list_next(n))
{
w = _nc_list_data(n);
watcher_internal_trigger(w, t, flags, level);
}
if (level == 0)
{
for (n = watch_list; n != NULL; n = x)
{
x = _nc_list_next(n);
w = _nc_list_data(n);
if (w->refcount == 0) watcher_release(w);
}
}
}
void
watcher_shutdown()
{
watcher_t *w;
list_t *n;
for (n = watch_list; n != NULL; n = _nc_list_next(n))
{
w = _nc_list_data(n);
watcher_release(w);
}
_nc_list_release_list(watch_list);
}
void
watcher_printf(watcher_t *w, FILE *f)
{
uint32_t i;
if (w == NULL)
{
fprintf(f, "-nil-\n");
return;
}
fprintf(f, "Watcher %u\n", w->wid);
fprintf(f, "Name:");
if (w->name == NULL) fprintf(f, " -nil-");
else for (i = 0; w->name[i] != NULL; i++) fprintf(f, " %s", w->name[i]);
fprintf(f, "\n");
fprintf(f, "Type: %u\n", w->type);
fprintf(f, "Refcount: %u\n", w->refcount);
fprintf(f, "Forward (%u):", w->count);
for (i = 0; i < w->count; i++) fprintf(f, " %u", w->fwd[i]);
fprintf(f, "\n");
if (w->sub_printf != NULL) w->sub_printf(w, f);
}
syntax highlighted by Code2HTML, v. 0.9.1