aboutsummaryrefslogtreecommitdiff
path: root/unix/boot/mkpkg/fdcache.c
blob: 7dfca1a3523207692dc8eb35d3cdc886c14d47da (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/*
 * FDCACHE -- Maintain a cache of filenames and their associated modification
 * dates.  This can greatly reduce the amount of time required to determine
 * which, if any, of the modules in a library need updating because an include
 * file they depend upon has been modified.
 *
 * External entry points:
 *
 *   l = m_fdate (fname)		# return file (modification) date
 *	m_fdinit (debug)		# initialize cache
 */

#define	MAX_FILES	20		/* size of the cache		*/
#define	SZ_NAME		32		/* size of filename slot	*/
#define	EOS		'\0'

struct _fdate {				/* cache list element structure	*/
	struct	_fdate *uplnk;
	struct	_fdate *dnlnk;
	int	nrefs;			/* number of references		*/
	int	chksum;			/* speeds searches		*/
	long	fdate;			/* file modification date	*/
	char	fname[SZ_NAME+1];	/* file name			*/
};

struct	_fdate fdcache[MAX_FILES];	/* the cache			*/
struct	_fdate *fd_head;		/* doubly linked list		*/
struct	_fdate *fd_tail;
int	fd_hits, fd_misses;

struct	_fdate *fd_unlink();
struct	_fdate *fd_tohead();
struct	_fdate *fd_totail();

long  m_fdate (char *fname);
void  m_fdinit (int debug);
int   fd_chksum (char *s);

extern  long         os_fdate (char *fname);


/* M_FDATE -- Get file modification date.  This is functionally equivalent to
 * os_fdate().
 */
long
m_fdate (char *fname)
{
	register struct _fdate *fd;
	register int	chksum;

	/* Look in the cache first.
	 */
	chksum = fd_chksum (fname);
	for (fd=fd_head;  fd != NULL;  fd=fd->dnlnk)
	    if (fd->chksum == chksum && strcmp (fname, fd->fname) == 0) {
		fd_tohead (fd_unlink (fd));
		fd->nrefs++;
		fd_hits++;
		return (fd->fdate);
	    }

	/* Cache miss.  Don't put in cache it name is too long.
	 */
	fd_misses++;
	if (strlen (fname) > SZ_NAME)
	    return (os_fdate (fname));

	/* Put fname in the cache.  Reuse slot at tail of list.
	 */
	fd = fd_tohead (fd_unlink (fd_tail));
	strncpy (fd->fname, fname, SZ_NAME);
	fd->chksum = fd_chksum (fname);
	fd->fdate  = os_fdate (fname);
	fd->nrefs  = 1;

	return (fd->fdate);
}


/* M_FDINIT -- Initialize (clear) the fdate cache.
 */
void
m_fdinit (int debug)
{
	register struct _fdate *fd;
	register int	i;
	int	total;

	if (debug) {
	    total = fd_hits + fd_misses;
	    printf ("file date cache: %d hits, %d misses, %d%% of %d\n",
		fd_hits, fd_misses, (total ? fd_hits * 100 / total : 0), total);

	    for (fd=fd_head;  fd != NULL;  fd=fd->dnlnk)
		if (fd->fname[0])
		    printf ("%3d %10ld (%05d) %s\n",
			fd->nrefs, fd->fdate, fd->chksum, fd->fname);

	    fd_hits   = 0;
	    fd_misses = 0;

	    fflush (stdout);
	}

	fd = fd_head = fd_tail = &fdcache[0];
	fd->uplnk   = NULL;
	fd->dnlnk   = NULL;
	fd->nrefs   = 0;
	fd->chksum  = -1;
	fd->fname[0] = EOS;

	for (i=1;  i < MAX_FILES;  i++) {
	    fd = fd_tohead (&fdcache[i]);
	    fd->fname[0] = EOS;
	    fd->chksum   = -1;
	    fd->nrefs    = 0;
	}
}


/* FD_TOHEAD -- Link a fdate struct at the head of the list.
 */
struct _fdate *
fd_tohead (register struct _fdate *fd)
{
	if (fd != fd_head) {
	    fd->uplnk = NULL;
	    fd->dnlnk = fd_head;
	    fd_head->uplnk = fd;
	    fd_head = fd;
	}

	return (fd);
}


/* FD_TOTAIL -- Link a fdate struct at the tail of the list.
 */
struct _fdate *
fd_totail (register struct _fdate *fd)
{
	if (fd != fd_tail) {
	    fd->uplnk = fd_tail;
	    fd->dnlnk = NULL;
	    fd_tail->dnlnk = fd;
	    fd_tail = fd;
	}

	return (fd);
}


/* FD_UNLINK -- Unlink an fdate struct.
 */
struct _fdate *
fd_unlink (register struct _fdate *fd)
{
	if (fd == fd_head)
	    fd_head = fd->dnlnk;
	if (fd == fd_tail)
	    fd_tail = fd->uplnk;

	if (fd->uplnk)
	    fd->uplnk->dnlnk = fd->dnlnk;
	if (fd->dnlnk)
	    fd->dnlnk->uplnk = fd->uplnk;
	
	return (fd);
}


/* FD_CHKSUM -- Compute the checksum of a character string.
 */
int
fd_chksum (char *s)
{
	register int sum=0;

	while (*s)
	    sum += *s++;

	return (sum);
}