|
|
1.1 root 1: /*
2: * This file contains a
3: * mini disc buffer cache manager.
4: */
5: #include <stdio.h>
6: #include <discbuf.h>
7:
8: DISCBUF *dblist;
9: FILE *dbfp;
10:
11: /*
12: * Claim a buffer and
13: * read block `block' into it.
14: * Return a pointer to the
15: * buffer.
16: */
17: DISCBUF *
18: dbread(block)
19: long block;
20: {
21: register DISCBUF *dbp;
22:
23: dbp = dbgrab(block);
24: if ((dbp->db_flag&DB_OK) == 0) {
25: lseek(fileno(dbfp), BUFSIZ*dbp->db_block, 0);
26: if (read(fileno(dbfp), dbp->db_data, BUFSIZ) != BUFSIZ)
27: dbfatal("cache read error, block %ld", block);
28: dbp->db_flag |= DB_OK;
29: }
30: return (dbp);
31: }
32:
33: /*
34: * This routine grabs a buffer
35: * and declares it to be the contents
36: * of block `block'.
37: * The data in the block is set to
38: * all zeros.
39: */
40: DISCBUF *
41: dbzero(block)
42: long block;
43: {
44: register DISCBUF *dbp;
45: register char *p;
46: register n;
47:
48: dbp = dbgrab(block);
49: dbp->db_flag = DB_OK;
50: p = dbp->db_data;
51: n = BUFSIZ;
52: do {
53: *p++ = 0;
54: } while (--n);
55: return (dbp);
56: }
57:
58: /*
59: * Buffer grab.
60: * Try to find a buffer that
61: * has the block in it.
62: * If not, use the oldest free
63: * buffer.
64: */
65: DISCBUF *
66: dbgrab(block)
67: long block;
68: {
69: register DISCBUF *dbp1, *dbp2;
70: register DISCBUF *fbp1, *fbp2;
71:
72: dbp1 = fbp1 = fbp2 = NULL;
73: dbp2 = dblist;
74: while (dbp2!=NULL && dbp2->db_block!=block) {
75: if (dbp2->db_refc == 0) {
76: fbp1 = dbp1;
77: fbp2 = dbp2;
78: }
79: dbp1 = dbp2;
80: dbp2 = dbp2->db_fp;
81: }
82: if (dbp2 == NULL) {
83: if (fbp2 == NULL)
84: dbfatal("cache full");
85: dbp1 = fbp1;
86: dbp2 = fbp2;
87: if ((dbp2->db_flag&DB_DIRT) != 0)
88: dbwrite(dbp2);
89: dbp2->db_flag = 0;
90: dbp2->db_block = block;
91: }
92: ++dbp2->db_refc;
93: if (dbp1 != NULL) {
94: dbp1->db_fp = dbp2->db_fp;
95: dbp2->db_fp = dblist;
96: dblist = dbp2;
97: }
98: return (dbp2);
99: }
100:
101: /*
102: * Flush the buffer cache. All
103: * dirty buffers get written out to
104: * the disc.
105: * If `flag' is true the buffer
106: * cache is released.
107: */
108: dbflush(flag)
109: {
110: register DISCBUF *dbp;
111: register DISCBUF *fbp;
112:
113: dbp = dblist;
114: while (dbp != NULL) {
115: if ((dbp->db_flag&(DB_OK|DB_DIRT)) == (DB_OK|DB_DIRT))
116: dbwrite(dbp);
117: if (flag) {
118: fbp = dbp;
119: dbp = dbp->db_fp;
120: free((char *) fbp);
121: } else {
122: dbp->db_flag = 0;
123: dbp->db_refc = 0;
124: dbp = dbp->db_fp;
125: }
126: }
127: if (flag)
128: dblist = NULL;
129: }
130:
131: /*
132: * Allocate a buffer cache.
133: * The argument `nbuf' is the number
134: * of buffers to claim.
135: */
136: dbclaim(nbuf)
137: {
138: register DISCBUF *dbp;
139:
140: if (dblist != NULL)
141: dbfatal("already claimed");
142: while (nbuf--) {
143: if ((dbp = (DISCBUF *) malloc(sizeof(DISCBUF))) == NULL)
144: dbfatal("no memory");
145: dbp->db_flag = 0;
146: dbp->db_refc = 0;
147: dbp->db_fp = dblist;
148: dblist = dbp;
149: }
150: }
151:
152: /*
153: * Write a buffer to the disc.
154: */
155: dbwrite(dbp)
156: register DISCBUF *dbp;
157: {
158: lseek(fileno(dbfp), BUFSIZ*dbp->db_block, 0);
159: if (write(fileno(dbfp), dbp->db_data, BUFSIZ) != BUFSIZ)
160: dbfatal("cache write error, block %ld", dbp->db_block);
161: }
162:
163: /*
164: * Release a buffer.
165: * The reference count is updated
166: */
167: dbfree(dbp, flag)
168: register DISCBUF *dbp;
169: {
170: dbp->db_flag |= flag;
171: if (--dbp->db_refc < 0)
172: dbfatal("refc < 0");
173: }
174:
175: /*
176: * Fatal errors.
177: */
178: dbfatal(a)
179: {
180: fprintf(stderr, "discbuf: %r\n", &a);
181: exit(1);
182: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.