/* This file is part of the Project Athena Palladium Print System.
 *
 *	$Source: $
 *	$Author: $
 *	$Header: $
 *
 *	Copyright (c) 1989 by the Massachusetts Institute of Technology.
 *	For copying and distribution information, see the file
 *	"mit-copyright.h". 
 */

/*
 * LWP_FORK is a macro which is defined if we are using a real threads
 * implementation (using forks rather than coroutines). If we are
 * using a coroutine based version, then the scheduler is a separate
 * process and has to manipulate the JOBS database on disk files.
 */

#ifndef __DB_H

#define __DB_H
#include "DBattribs.h"
#include "mit-copyright.h"
#include <stdio.h>
#include <strings.h>
#include <syslog.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/param.h>
#include <sys/dir.h>
#include <sys/stat.h>

/* Symbolic name for the entity type */
#define	SERVER		0
#define SPVR		1
#define	PRINTER		2
#define LOGPRINTER	3
#define JOB		4
#define FONTS		5
#define FORMS		6
#define MEDIA		7
#define TYPE		8
#define ASSN		9
#define QUEUE		10
#define SCHEDULER	11
#define FONTASSN        12
#define FORMASSN        13
#define QUOTASERVER	14
#define LOGGERSERVER	15

/* Total number of entity types */
#define NUMENTITYTYPES	16

/* 
 * A keyword value (at present!) can be a CHARPTR , an INT, a LIST
 * type. These go in the keywordTable structure also.
 */
#define NULLTYPE	0
#define	CHARPTR		1
#define	INT		2
#define LIST		4

/* NULL casts to make comparisons and lint happy */
#define	LNULL	(struct List *)0
#define ENULL   (Entity)0
#define FNULL	(FILE *)0

/* DB library error codes */
/* These have gone in the pddb_err.et file for ATHENA ifdef */
#ifdef ATHENA
#include "com_err.h"
#include "pddb_err.h"
#else !(ATHENA)
#define	PDDB_NOSCHATT	1	/* No such attribute */
#define PDDB_INVALCALL	2	/* Invalid call as FindNext() called */
				/* after a NULL Find() *or* FindNext() */
#define PDDB_WRONGFMT	3	/* wrong format passed */
#define PDDB_NAMEHASH	4	/* Hashing done on "Name" attribute */
				/* only */
#define PDDB_BADCONFIG	5	/* Bad config file */
#define PDDB_BADTABLE  	6	/* Bad Keyword table */
#define PDDB_TYPEMISMATCH   7	/* Type mismatch in config file */
#define PDDB_NOCONFIG	8	/* Config file missing */
#define PDDB_KEYOVERF	9	/* Max keywords overflow */
#define PDDB_LEVOVERF	10	/* nesting level overflow */
#define PDDB_ENTOVERF	11	/* Num of entries in each level */
#define PDDB_MEMFAIL	12	/* malloc() failed */
#define PDDB_ENTLKUP	13	/* EntityLookup() failed */
#define PDDB_BRKHEIRNAM    14   /* BreakHeirarchicalName() failed */
#define PDDB_ICDREQ        15   /* ICD type requested in RetrieveKey() */
#define PDDB_INVALTYPE     16   /* Invalid type from DB in RetrieveKey() */
#define PDDB_FILEEXISTS	   17	/* SPVR *or* jf.. File already exists */    
#endif !(ATHENA)

/* General defines */
#define READ	0	/* Read lock */
#define WRITE	1	/* Write lock */
#define APPEND  2	/* Open file in append mode */

#ifndef  FALSE
#define	FALSE	0
#endif

#ifndef  NO
#define	NO	0
#endif

#ifndef  TRUE
#define	TRUE	1
#endif

#ifndef YES
#define	YES	1
#endif

#define	Bool	int
#define JOBPREFIX	"jf.."
#define DATAPREFIX	"df.."
#define DIRMOD		0755
#define FILMOD		0660
#define CLIENTDIR	"ClientDir"
#define SUPERVISORDIR	"SupervisorDir"
#define MAX_NAME_LENGTH	128
#define VERBOSE 1
#define NOVERBOSE 0


#define SPVRPREFIX	"spvr_"		/* Supervisor disk file prefix */
#define SOCKPREFIX	"palladium_"	/* AF_UNIX socket pefix */
#define CHANGEFILESUFFIX "ChangeLog"    /* logfile for dynamic changes */

extern int lineno;		/* Line count for parser */
extern FILE *yyin;		/* input configuration file */
extern int rVParsing;		/* R we parsing */
extern int dbErrNum;		/* Holds the DB error number */
extern int numEntities[];	/* Nth entity of etype being parsed in */
				/* the configuration file */
extern char *spoolDir;	       	/* holds server spool dir name */
extern struct List *Update_log; /* Log record for changes, used in recovery */
extern short  doChangeFile;     /* Logging to Update_log enabled ?  */
extern int numKeywordEntries;	/* Holds current num of entries */
extern int allocedKeywordEntries;	/* Holds current spaces alloc'ed */
extern FILE *changeFile;        /* Logfile for dynamic changes */

/* Error stuff */
extern int errno, sys_nerr;
extern char *sys_errlist[];

/* scheduling criteria SETTABLE by calling service (defaults to FCFS) */
#define SCH_FCFS	0	/* First Come First Served */
#define SCH_PRI		1	/* Priority */
#define SCH_SJF		2	/* Shortest Job First */

extern int schedulingCriteria;
extern int defaultSchedulingFunction();	/* The default Scheduling function */
typedef int (*pfint)();			/* pointer to function returning int */
extern int (*schedulingFunction)();


/* Struct definitions follow */

/* struct for keyword name and their corresponding type */
struct KeywordNType {
  char *keyword;
  short vtype;
};

/* The main structure which stores all the entity information */
struct entry {
  char *e_name;		/* name of capability...points to */
			/* KeywordMap */
  short e_vtype;	/* Type of value */
  union {
    char *u_str_value;
    int  u_int_value;
    char **u_list_value;
  } e_union;
};

#define	e_str_value	e_union.u_str_value
#define	e_int_value	e_union.u_int_value
#define	e_list_value	e_union.u_list_value

/* 
 * structure used for building a list of job files. Later may be used
 * for other things as the queue structure expands.
 */
struct queue {
  time_t q_time;		/* Modification time */
  char   q_name[MAXPATHLEN+1];	/* job file name (starts with "jf..") */
};

typedef struct entry *Entity;

struct List {
  Entity l_entity;
  struct List *l_next;
  struct List *l_prev;
};

/* Holds the head pointer for entities */
extern struct List *head[];


#define HASHMODULO	32

/* Job Queue related structures */
struct Map {
  char *m_qName;		/* name of queue */
  int  m_qIndex;		/* index into array of queues */
};

extern struct Map *map;
extern struct List **jobQueue;

/* Stores all the keywords for EntityTypes & AttributeTypes */
extern struct KeywordNType initialKeywordTable[];
extern struct KeywordNType *keywordTable;

/* Name and return-types of external functions */
extern int Hash();
extern struct List *Create(), *CreateList(), 
  *Find(), *FindNext(), *UpdateList(), *FindAll();
FILE *DbLock();

extern int SetKeyTmp(), MakeTmpEntrySolid(), FreeTmpEntry(), 
  InsertJob(), DetachJob();
extern Entity CreateEntityFile();
extern struct List *CreateListJobId(), *CreateListQueue(),
  *CreateListFile(), *CreateListSpvrName(), *CopyEntry();
extern char *GetJobFileName(), *GetQueueDirName(), *CreateJFName(), 
  *CreateDFName();
extern char *Savestr(), **Savelist(), *RetrieveKey();

extern void FreeFindPtrList(), RecoverSpvrs(), RecoverServerFromFile();

extern int (*SetHookSchedulingFunction())();
extern int (*ResetHookSchedulingFunction())();

/* Some macros to make life easier */

#define DBMALLOC(t)	(t *)malloc(sizeof(t))
#define	SIZEOF(s,t)	(sizeof(s)/sizeof(t))

/* Head is the head of list, and ptr is a new element inserted at start */
/* IMP: The l_prev of Head points to the tail of the list */
#define INSERT(Head,ptr)	{ \
			    if ((Head) == LNULL) { \
				(Head) = ptr; \
				(Head)->l_next = LNULL; \
				(Head)->l_prev = ptr; \
			     } else { \
				ptr->l_next = (Head); \
				ptr->l_prev = (Head)->l_prev; \
				(Head)->l_prev = ptr; \
			        (Head) = ptr; \
			      } \
			    }

/* Head is the head of list, and ptr is a new element appended to end */
/* IMP: The l_prev of Head points to the tail of the list */
#define APPENDL(Head,ptr)	{ \
			    if ((Head) == LNULL) { \
				(Head) = ptr; \
				(Head)->l_next = LNULL; \
				(Head)->l_prev = ptr; \
			     } else { \
			        (Head)->l_prev->l_next = ptr; \
				ptr->l_prev = (Head)->l_prev; \
				ptr->l_next = LNULL; \
				(Head)->l_prev = ptr; \
			      } \
			    }

/* Head is head of the list, and ptr is an element to be deleted  	*/
/* DELETE is called only when Head & ptr are non-NULL 			*/
/* IMP: We have to take care of updating l_prev prointers from the 	*/
/*      head of the list to the last element 				*/
#define DELETE(Head,ptr)	{ \
			  if ( ptr == (Head) ) {\
			    (Head) = (Head)->l_next; \
			    /* Update l_prev if atleast 1 more elt */ \
			    if ( ptr->l_next != LNULL ) \
			      (Head)->l_prev = ptr->l_prev; \
			   } \
			  else if ( ptr->l_next == LNULL ){ \
			         /* Here there will be always 2 */ \
				 /* or more elements */ \
				 ptr->l_prev->l_next = LNULL; \
				 (Head)->l_prev = ptr->l_prev; \
				 } \
			  else { \
			    ptr->l_prev->l_next = ptr->l_next; \
			    ptr->l_next->l_prev = ptr->l_prev; \
			   } \
			  /* Free space, don't free l_entity as */ \
			  /* there may be more pointers to it */ \
			  free((char *)ptr); \
			 }
				

#define HEAD(etype)	head[etype]

#define CURRENTPTR(etype)	currentDbPtr[etype]

#define VALUE(vtype)	(vtype==CHARPTR?entity[eIndex].e_str_value:\
			 (vtype==INT?entity[eIndex].e_int_value:\
			  (vtype==LIST?entity[eIndex].e_list_value:\
			   entity[eIndex].e_icd)))

#define HASHEDSTRING(etype)	(etype==JOB?"JobId":"Name")

#define HASHEDSTRINGLEN(etype)	(etype==JOB?5:4)

#if defined(BSD4_3)
#define OPENLOG(x) openlog("PdDBlib(x)",LOG_PID,LOG_LOCAL2); setlogmask(LOG_MASK(LOG_INFO))
#define CLOSELOG() closelog()
#endif 

#if !defined(BSD4_3) && defined(ULTRIX)
#define OPENLOG(x) openlog("PdDBlib(x)",LOG_PID)
#define CLOSELOG() closelog()
#endif

#if !defined(BSD4_3) && !defined(ULTRIX) && defined(HPUX)
#define OPENLOG(x) 
#define CLOSELOG() 
#endif

#endif __DB_H
