/*
 * Name: psinode.h
 * Description: Interface and basic funtions of pseudo inode handling.
 * Author: Christian Starkjohann <cs@hal.kph.tuwien.ac.at>
 * Date: 1996-12-06
 * Copyright: GNU-GPL
 * Tabsize: 4
 */
 

#define	REFCOUNT_MAX	65535		/* limited by unsigned short */
#define	PATHBUF_SIZE	2048		/* buffer size for server pathes */
#define	DOS_PATHSEP		'\\'		/* path separator in DOS */
#define	HASH_MAGIC_L	0x12345678
#define	HASH_MAGIC_H	0x87654321

/* ------------------------------------------------------------------------- */

typedef struct psinode{
	struct psinode	*next;
	struct psinode	**prevnext;	/* doubly linked list for LRU queue */
	long long		ino;		/* full hash value */
	struct psinode	*parent;	/* parent directory */
	unsigned short	refcount;	/* reference counting for directories */
	char			name[1];	/* name of the file */
}psinode_t;

typedef struct list{
	void		*head;			/* first element in list */
	void		**tail;			/* pointer to 'next' entry of last element */
}list_t;

typedef struct psinode_table{
	psinode_t	**table;		/* the table itself */
	int			table_size;		/* size of hashtable */
	int			load;			/* number of inodes in hashtable */
	int			fill_limit;		/* defines fill grade of hashtable */
	int			delete_on_gc;	/* delete this much if load > fill_limit */
	int			max_search;		/* number of places to search */
	list_t		lru;			/* list for least recently used mechanism */
}psinode_table_t;

/* ------------------------------------------------------------------------- */

static inline void	list_init(list_t *list)
{
	list->head = NULL;
	list->tail = &list->head;
}

static inline void	list_remove_element(list_t *list, void *e)
{
struct _entry{struct _entry *next; struct _entry **prevnext;}	*entry = e;

	*entry->prevnext = entry->next;
	if(list->tail == (void **)&entry->next){	/* if we are the last entry */
		list->tail = (void *)entry->prevnext;	/* previous is last one now */
	}
	if(entry->next != NULL){
		entry->next->prevnext = entry->prevnext;
	}
	entry->prevnext = NULL;
	entry->next = NULL;
}

static inline void	list_append(list_t *list, void *e)
{
struct _entry{struct _entry *next; struct _entry **prevnext;}	*entry = e;

	entry->prevnext = (void *)list->tail;
	*list->tail = entry;
	list->tail = (void *)&entry->next;
	entry->next = NULL;
}

static inline void	list_move_to_end(list_t *list, void *e)
{
struct _entry{struct _entry *next; struct _entry **prevnext;}	*entry = e;

	if(entry->next == NULL)	/* we are already the last! */
		return;
	*entry->prevnext = entry->next;		/* take us out of the list */
	entry->next->prevnext = entry->prevnext;

	entry->prevnext = (void *)list->tail;		/* put us at the end */
	*list->tail = entry;
	list->tail = (void *)&entry->next;
	entry->next = NULL;
}

/* ------------------------------------------------------------------------- */

extern psinode_table_t	psitable;	/* table of pseudo-inodes */
extern long long		root_inum;	/* pseudo inode numbe for root */

/* ------------------------------------------------------------------------- */

int		psi_index(long long ino);
long long	psi_inum(long long parent_ino, char *name);
int		psi_lookup(int parent_i, char *name, long long *ino);
void	psi_delete(long long ino);
int		psi_define_root(char *name, long long *ino);
char	*psi_to_path(int index, char pathsep, char *ending);
void	psi_init(int table_size, int low_mark, int high_mark);
