/* Copyright (C) 1993,1994 by the author(s).
 
 This software is published in the hope that it will be useful, but
 WITHOUT ANY WARRANTY for any part of this software to work correctly
 or as described in the manuals. See the ShapeTools Public License
 for details.

 Permission is granted to use, copy, modify, or distribute any part of
 this software but only under the conditions described in the ShapeTools 
 Public License. A copy of this license is supposed to have been given
 to you along with ShapeTools in a file named LICENSE. Among other
 things, this copyright notice and the Public License must be
 preserved on all copies.
 */
/*
 * AtFS -- Attribute Filesystem
 *
 * afkeys.c -- handle revision keys
 *
 * Author: Andreas Lampen (Andreas.Lampen@cs.tu-berlin.de)
 *
 * $Header: afkeys.c[7.0] Fri Jun 25 14:31:58 1993 andy@cs.tu-berlin.de frozen $
 */

#include "atfs.h"

/*================================================================
 *	af_buildkey
 *================================================================*/

EXPORT int af_buildkey (list, gen, rev, key)
     Af_revlist *list;
     int 	gen;
     int	rev;
     Af_key	*key; /* out */
{
  register int i = list->af_listlen-1;;
  
  key->af_ldes = list;
  while (!(list->af_list[i].af_class & AF_VALID) ||
	 (list->af_list[i].af_gen != gen) ||
	 (list->af_list[i].af_rev != rev)) {
    i--;
    if (i == -1)
      FAIL ("buildkey", "", AF_ENOREV, ERROR);
  }
  key->af_lpos = i;
  return (AF_OK);
}

/*================================================================
 *	af_gbuskey
 *================================================================*/

EXPORT Af_key *af_gbuskey (list)
     Af_revlist *list;
{
  static Af_key busykey;

  busykey.af_ldes = list;
  busykey.af_lpos = 0;
  return (&busykey);
}


 /*================================================================
 *	af_glastkey
 *================================================================*/

EXPORT Af_key *af_glastkey (list)
     Af_revlist *list;
{
  register int i = list->af_listlen-1;
  static Af_key lastkey;

  lastkey.af_ldes = list;
  while (!(list->af_list[i].af_class & AF_VALID)) {
    i--;
    if (i == 0)
      return (NULL);
  }
  lastkey.af_lpos = i;
  return (&lastkey);
}

/*================================================================
 * af_glastgenkey
 *================================================================*/

EXPORT Af_key *af_glastgenkey (list, gen)
     Af_revlist *list;
     int gen;
{
  register int i = list->af_listlen-1;
  static Af_key lastgenkey;

  lastgenkey.af_ldes = list;
  while (!(list->af_list[i].af_class & AF_VALID) ||
	 (list->af_list[i].af_gen != gen)) {
    i--;
    if (i == 0)
      return (NULL);
  }
  lastgenkey.af_lpos = i;
  return (&lastgenkey);
}

/*================================================================
 * af_gfreepos -- search space for new list entry
 *                preserve increasing order
 *================================================================*/

EXPORT int af_gfreepos (list)
     Af_revlist *list;
{
  register int i = list->af_listlen-1;

  while (!(list->af_list[i].af_class & AF_VALID) && (i >= 0))
    i--;

  if (i == list->af_listlen-1)
    return (ERROR);

  if (!(list->af_list[i].af_class & AF_VALID) && (i == 0))
    return (0);

  return (i+1);
}

/*================================================================
 * af_glastgenpos
 *================================================================*/

EXPORT int af_glastgenpos (list, gen)
     Af_revlist *list;
     int gen;
{
  register int i = list->af_listlen-1;

  while (!(list->af_list[i].af_class & AF_VALID) ||
	 (list->af_list[i].af_gen != gen)) {
    i--;
    if (i == 0)
      return (ERROR);
  }
  return (i);
}

/*===================
 * afIncreaseAccess
 *===================*/

EXPORT void afIncreaseAccess (key)
     Af_key *key;
{
  (key->af_ldes)->af_access++;
  VATTR(key).af_nrefs++;
#ifdef AFTRACE
  fprintf (stderr, "AF_TRACE (key): +++%s\n", af_retattr (key, AF_ATTBOUNDPATH));
#endif
}

/*===================
 * afDecreaseAccess
 *===================*/

EXPORT void afDecreaseAccess (key)
     Af_key *key;
{
  (key->af_ldes)->af_access--;
  VATTR(key).af_nrefs--;
#ifdef AFTRACE
  fprintf (stderr, "AF_TRACE (key): ---%s\n", af_retattr (key, AF_ATTBOUNDPATH));
#endif
}

/*================================================================
 * af_dropkey
 *================================================================*/

EXPORT int af_dropkey (key)
     Af_key *key;
{
  if (afAccessAso (key, 0))
    FAIL ("dropkey", "", AF_EINVKEY, ERROR);

  /* decrease reference count in corresponding archive and in attrbuf */
  afDecreaseAccess (key);
  return (AF_OK);
}

/*================================================================
 * af_dropall
 *================================================================*/

extern Af_revlist *af_lists;

EXPORT int af_dropall ()
{
  Af_revlist *list;
  register int i;

  list = af_lists;
  while (list) {
    for (i=0; i<list->af_listlen; i++)
      list->af_list[i].af_nrefs = 0;
    list->af_access = 0;
    list = list->af_next;
  }
#ifdef AFTRACE
  fprintf (stderr, "AF_TRACE (key): ----------- dropped all ------------\n");
#endif
  return (AF_OK);
}
