Blob Blame History Raw
/*
 * "$Id$"
 *
 *   Timeout functions for the Common UNIX Printing System (CUPS).
 *
 *   Copyright (C) 2010, 2011 Red Hat, Inc.
 *   Authors:
 *     Tim Waugh <twaugh@redhat.com>
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *
 *   Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 *   Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *   COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 *   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 *   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 *   OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Contents:
 *
 *   cupsdInitTimeouts()  - Initialise timeout structure.
 *   cupsdAddTimeout()    - Add a timed callback.
 *   cupsdNextTimeout()   - Find the next enabled timed callback.
 *   cupsdUpdateTimeout() - Adjust the time of a timed callback or disable it.
 *   cupsdRemoveTimeout() - Discard a timed callback.
 *   compare_timeouts()   - Compare timed callbacks for array sorting.
 */

#include <config.h>

#ifdef HAVE_AVAHI /* Applies to entire file... */

/*
 * Include necessary headers...
 */

#include "cupsd.h"

#if defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
#  include <malloc.h>
#endif /* HAVE_MALLOC_H && HAVE_MALLINFO */

#ifdef HAVE_AVAHI
#  include <avahi-common/timeval.h>
#endif /* HAVE_AVAHI */


struct _cupsd_timeout_s
{
  struct timeval when;
  int enabled;
  cupsd_timeoutfunc_t callback;
  void *data;
};

/*
 * Local functions...
 */

/*
 * 'compare_timeouts()' - Compare timed callbacks for array sorting.
 */

static int
compare_addrs (void *p0, void *p1)
{
  if (p0 == p1)
    return (0);
  if (p0 < p1)
    return (-1);
  return (1);
}

static int
compare_timeouts (cupsd_timeout_t *p0, cupsd_timeout_t *p1)
{
  int addrsdiff = compare_addrs (p0, p1);
  int tvdiff;

  if (addrsdiff == 0)
    return (0);

  if (!p0->enabled || !p1->enabled)
  {
    if (!p0->enabled && !p1->enabled)
      return (addrsdiff);

    return (p0->enabled ? -1 : 1);
  }

  tvdiff = avahi_timeval_compare (&p0->when, &p1->when);
  if (tvdiff != 0)
    return (tvdiff);

  return (addrsdiff);
}


/*
 * 'cupsdInitTimeouts()' - Initialise timeout structures.
 */

void
cupsdInitTimeouts(void)
{
  Timeouts = cupsArrayNew ((cups_array_func_t)compare_timeouts, NULL);
}


/*
 * 'cupsdAddTimeout()' - Add a timed callback.
 */

cupsd_timeout_t *				/* O - Timeout handle */
cupsdAddTimeout(const struct timeval *tv,	/* I - Absolute time */
		cupsd_timeoutfunc_t cb,		/* I - Callback function */
		void *data)			/* I - User data */
{
  cupsd_timeout_t *timeout;

  timeout = malloc (sizeof(cupsd_timeout_t));
  if (timeout != NULL)
  {
    timeout->enabled = (tv != NULL);
    if (tv)
    {
      timeout->when.tv_sec = tv->tv_sec;
      timeout->when.tv_usec = tv->tv_usec;
    }

    timeout->callback = cb;
    timeout->data = data;
    cupsArrayAdd (Timeouts, timeout);
  }

  return timeout;
}


/*
 * 'cupsdNextTimeout()' - Find the next enabled timed callback.
 */

cupsd_timeout_t *		/* O - Next enabled timeout or NULL */
cupsdNextTimeout(long *delay)	/* O - Seconds before scheduled */
{
  cupsd_timeout_t *first = cupsArrayFirst (Timeouts);
  struct timeval curtime;

  if (first && !first->enabled)
    first = NULL;

  if (first && delay)
  {
    gettimeofday (&curtime, NULL);
    if (avahi_timeval_compare (&curtime, &first->when) > 0)
    {
      *delay = 0;
    } else {
      *delay = 1 + first->when.tv_sec - curtime.tv_sec;
      if (first->when.tv_usec < curtime.tv_usec)
	(*delay)--;
    }
  }

  return (first);
}


/*
 * 'cupsdRunTimeout()' - Run a timed callback.
 */

void
cupsdRunTimeout(cupsd_timeout_t *timeout)	/* I - Timeout */
{
  if (!timeout)
    return;
  timeout->enabled = 0;
  if (!timeout->callback)
    return;
  timeout->callback (timeout, timeout->data);
}

/*
 * 'cupsdUpdateTimeout()' - Adjust the time of a timed callback or disable it.
 */

void
cupsdUpdateTimeout(cupsd_timeout_t *timeout,	/* I - Timeout */
		   const struct timeval *tv)	/* I - Absolute time or NULL */
{
  cupsArrayRemove (Timeouts, timeout);
  timeout->enabled = (tv != NULL);
  if (tv)
  {
    timeout->when.tv_sec = tv->tv_sec;
    timeout->when.tv_usec = tv->tv_usec;
  }
  cupsArrayAdd (Timeouts, timeout);
}


/*
 * 'cupsdRemoveTimeout()' - Discard a timed callback.
 */

void
cupsdRemoveTimeout(cupsd_timeout_t *timeout)	/* I - Timeout */
{
  cupsArrayRemove (Timeouts, timeout);
  free (timeout);
}


#endif /* HAVE_AVAHI ... from top of file */

/*
 * End of "$Id$".
 */