Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 663 lines (577 sloc) 16.381 kb
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
1 /* session.c */
2 /* Copyright 1995 by Steve Kirkendall */
3
4
5 #include "elvis.h"
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
6 #ifdef FEATURE_RCSID
7 char id_session[] = "$Id: session.c,v 2.30 2003/10/17 17:41:23 steve Exp $";
8 #endif
9
10 #undef LOG_SESSION
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
11
12 /* This file contains the session functions, which implement a cache and
13 * block-locking semantics on the session file.
14 */
15
16 /*----------------------------------------------------------------------------*/
17 /* session block cache */
18
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
19 #define MAXLOCKS 30
20
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
21 typedef struct blkcache_s
22 {
23 struct blkcache_s *next; /* another block with same hash value */
24 struct blkcache_s *older,*newer;/* the next-older block in the cache */
25 COUNT locks; /* lock counter */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
26 ELVBOOL dirty; /* does the block need to be rewritten? */
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
27 BLKNO blkno; /* block number of this block */
28 BLKTYPE blktype; /* type of data in this block */
29 BLK *buf; /* contents of the block */
30 #ifdef DEBUG_SESSION
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
31 char *lockfile[MAXLOCKS]; /* name of source file that locked block */
32 int lockline[MAXLOCKS]; /* line number in source file */
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
33 #endif
34 } CACHEENTRY;
35
36
37 #if USE_PROTOTYPES
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
38 static void delcache(CACHEENTRY *item, ELVBOOL thenfree);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
39 static void addcache(CACHEENTRY *item);
40 static CACHEENTRY *findblock(_BLKNO_ blkno);
41 static void flushblock(CACHEENTRY *bc);
42 #endif
43
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
44 #ifdef DEBUG_SESSION
45 static char *blktypename[] =
46 {
47 "SES_NEW","" "SES_SUPER","" "SES_SUPER2","" "SES_BUFINFO","" "SES_BLKLIST","" "SES_CHARS"
48 };
49 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
50
51 static long oldblkhash; /* previous value of o_blkhash option */
52 static CACHEENTRY **hashed; /* hash table */
53 static CACHEENTRY *newest; /* pointer to newest item in cache */
54 static CACHEENTRY *oldest; /* pointer to oldest item in cache */
55 static int ncached; /* number of items in cache */
56 static COUNT *alloccnt; /* array of allocation counts per block */
57 static int nblocks; /* size of alloccnt array */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
58 #ifdef DEBUG_SESSION
59 static BLKTYPE *alloctype; /* types of blocks, parallel to alloccnt[] */
60 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
61
62
63 /* This function deletes an item from the block cache. Optionally, it will
64 * also free the item.
65 */
66 static void delcache(item, thenfree)
67 CACHEENTRY *item; /* cache item to be removed from cache */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
68 ELVBOOL thenfree; /* if ElvTrue, item is freed after removal */
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
69 {
70 CACHEENTRY *scan, *lag;
71 int i;
72
73 assert(item != NULL && (item->locks == 0 || !thenfree));
74
75 /* if the item is dirty & we're completely deleting it, then flush it */
76 if (thenfree && item->dirty)
77 {
78 blkwrite(item->buf, item->blkno);
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
79 o_blkwrite++;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
80 }
81
82 /* delete the item from the newest/oldest list */
83 if (item == newest)
84 {
85 newest = item->older;
86 }
87 else
88 {
89 item->newer->older = item->older;
90 }
91 if (item == oldest)
92 {
93 oldest = item->newer;
94 }
95 else
96 {
97 item->older->newer = item->newer;
98 }
99
100 /* delete the item from the hashed list */
101 i = item->blkno % o_blkhash;
102 if (hashed[i] == item)
103 {
104 hashed[i] = item->next;
105 }
106 else
107 {
108 for (lag = hashed[i], scan = lag->next; scan != item; lag = scan, scan = scan->next)
109 {
110 assert(scan != NULL);
111 }
112 lag->next = scan->next;
113 }
114
115 /* if we're supposed to free it, do that */
116 if (thenfree)
117 {
118 safefree(item->buf);
119 safefree(item);
120 }
121 else
122 {
123 item->older = item->newer = NULL;
124 }
125
126 /* and count it */
127 ncached--;
128 }
129
130 /* This function adds an item to the "newest" end of the block cache, and also
131 * the hash list. Before it does this, it checks the overall size of the cache
132 * and if it has reached the maximum, it tries to delete the oldest unlocked
133 * item.
134 */
135 static void addcache(item)
136 CACHEENTRY *item; /* item to be added to cache */
137 {
138 CACHEENTRY *scan;
139 int i;
140
141 /* if this would push the cache past its limit, then try to delete
142 * the oldest unlocked block.
143 */
144 while (ncached >= o_blkcache)
145 {
146 for (i = 0, scan = oldest; scan && scan->locks > 0; scan = scan->newer, i++)
147 {
148 }
149 if (scan)
150 {
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
151 delcache(scan, ElvTrue);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
152 }
153 else
154 {
155 /* cache size will exceed blkcache... no big deal */
156 #ifdef DEBUG_SESSION
157 fprintf(stderr, "%d blocks locked\n", i);
158 #endif
159 break;
160 }
161 }
162
163 /* if this is the first item in the cache, then this is "oldest" */
164 if (!oldest)
165 {
166 oldest = item;
167 }
168
169 /* insert this item at the "newest" end of the cache list */
170 item->older = newest;
171 if (newest) newest->newer = item;
172 newest = item;
173
174 /* also insert it into the hash table list */
175 i = item->blkno % o_blkhash;
176 item->next = hashed[i];
177 hashed[i] = item;
178
179 /* also count it */
180 ncached++;
181 }
182
183 /* Find a block in the cache. If the block isn't in the cache, return NULL */
184 static CACHEENTRY *findblock(blkno)
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
185 _BLKNO_ blkno; /* physical block number of block to find */
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
186 {
187 CACHEENTRY *scan;
188 int i;
189
190 /* if newest item in cache, return it in a hurry! */
191 if (newest && newest->blkno == blkno)
192 {
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
193 o_blkhit++;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
194 return newest;
195 }
196
197 /* reallocate the hash table if first call or blkhash has changed */
198 if (!hashed || o_blkhash != oldblkhash)
199 {
200 /* free the old hash table, if any */
201 if (hashed)
202 {
203 safefree(hashed);
204 }
205
206 /* allocate a new hash table */
207 hashed = (CACHEENTRY **)safekept((int)o_blkhash, sizeof(CACHEENTRY *));
208
209 /* put each cached block into the appropriate hash slot */
210 for (scan = oldest; scan; scan = scan->newer)
211 {
212 i = scan->blkno % o_blkhash;
213 scan->next = hashed[i];
214 hashed[i] = scan;
215 }
216
217 oldblkhash = o_blkhash;
218 }
219
220 /* search for the block */
221 for (scan = hashed[blkno % o_blkhash];
222 scan && scan->blkno != blkno;
223 scan = scan->next)
224 {
225 }
226
227 /* if found, move it to the newest end of the cache list */
228 if (scan)
229 {
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
230 delcache(scan, ElvFalse);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
231 addcache(scan);
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
232 o_blkhit++;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
233 return scan;
234 }
235
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
236 o_blkmiss++;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
237 return NULL;
238 }
239
240 /*----------------------------------------------------------------------------*/
241 /* Open a session file. For any error, issue an error message and
242 * exit without ever returning.
243 */
244 void sesopen(force)
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
245 ELVBOOL force; /* if ElvTrue, open even if "in use" flag is set */
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
246 {
247 BLK *tmp;
248
249 /* allocate a temporary buffer for the superblock */
250 tmp = (BLK *)safealloc((int)o_blksize, sizeof(char));
251 tmp->super.magic = SESSION_MAGIC;
252 tmp->super.blksize = (COUNT)o_blksize;
253
254 /* open the session file */
255 if (!blkopen(force, tmp))
256 {
257 msg(MSG_FATAL, "already in use");
258 }
259
260 /* use the block size denoted in the superblock */
261 o_blksize = tmp->super.blksize;
262 o_blkfill = SES_MAXCHARS * 9/10;
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
263 /* toto: limit range of blkfill values to "1:SES_MAXCHARS" */
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
264
265 /* free the superblock buffer */
266 safefree(tmp);
267
268 /* allocate an initial allocation count table. It'll grow later. */
269 alloccnt = (COUNT *)safealloc(1, sizeof(COUNT));
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
270 #ifdef DEBUG_SESSION
271 alloctype = (BLKTYPE *)safealloc(1, sizeof(BLKTYPE));
272 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
273 nblocks = 1;
274 alloccnt[0] = 1; /* so superblock is always allocated */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
275 #ifdef DEBUG_SESSION
276 alloctype[0] = SES_SUPER;
277 #endif
278
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
279 }
280
281 /* Flush all dirty blocks in the cache, and then close the session
282 * file. Elvis calls this just before exiting.
283 */
284 void sesclose()
285 {
286 BLK *tmp;
287
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
288 /* if session file was never opened, then we don't need to close it */
289 if (nblocks == 0)
290 return;
291
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
292 /* flush any dirty blocks */
293 sessync();
294
295 /* close the session file */
296 tmp = (BLK *)safealloc((int)o_blksize, sizeof(char));
297 blkclose(tmp);
298 safefree(tmp);
299 }
300
301 /*----------------------------------------------------------------------------*/
302 /* Read the requested block into the cache, and lock it. Return
303 * a pointer to the block's data in the cache.
304 */
305 #ifdef DEBUG_SESSION
306 BLKNO _seslock(file, line, blkno, forwrite, blktype)
307 char *file; /* name of source file that called this func */
308 int line; /* line number of source file */
309 #else
310 BLKNO seslock(blkno, forwrite, blktype)
311 #endif
312 _BLKNO_ blkno; /* BLKNO of block to be locked */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
313 ELVBOOL forwrite; /* if ElvTrue, lock it for writing */
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
314 BLKTYPE blktype; /* type of data in the block */
315 {
316 CACHEENTRY *bc, *newp;
317
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
318 #ifdef LOG_SESSION
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
319 fprintf(stderr, "%s:%d: seslock(%d, %s, %s)...\n", file, line,
320 blkno, forwrite ? "True" : "False", blktypename[blktype]);
321 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
322 assert((int)blkno < nblocks && alloccnt[blkno] > 0);
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
323 #ifdef DEBUG_SESSION
324 if (alloctype[blkno] != blktype)
325 {
326 fprintf(stderr, "seslock() called from %s:%d with wrong block type.\n",
327 file, line);
328 fprintf(stderr, "blkno=%d, forwrite=%s, blktype=%s, alloctype[%d]=%s\n",
329 blkno, forwrite?"True":"False", blktypename[blktype],
330 blkno, blktypename[alloctype[blkno]]);
331 fprintf(stderr, "alloccnt[%d]=%d\n", blkno, alloccnt[blkno]);
332 }
333 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
334
335 /* try to find the block in the cache */
336 bc = findblock(blkno);
337
338 /* if not in the cache, then read it into a new cache item */
339 if (!bc)
340 {
341 bc = (CACHEENTRY *)safekept(1, sizeof(CACHEENTRY));
342 bc->buf = (BLK *)safekept((int)o_blksize, sizeof(char));
343 bc->blkno = blkno;
344 bc->blktype = blktype;
345 blkread(bc->buf, bc->blkno);
346 addcache(bc);
347 }
348
349 /* if for write, and its allocation count is greater than 1, then
350 * "copy on write" means we have to copy this block right now.
351 */
352 if (forwrite && alloccnt[blkno] > 1)
353 {
354 /* copy-on-write should only be necessary for CHARS blocks */
355 assert(blktype == SES_CHARS);
356
357 /* decrement the allocation count of the old block */
358 alloccnt[blkno]--;
359
360 /* allocate a new block */
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
361 blkno = sesalloc(0, blktype);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
362 newp = findblock(blkno);
363 if (!newp)
364 {
365 newp = (CACHEENTRY *)safealloc(1, sizeof(CACHEENTRY));
366 newp->buf = (BLK *)safealloc((int)o_blksize, sizeof(char));
367 newp->blkno = blkno;
368 newp->blktype = blktype;
369 addcache(newp);
370 }
371
372 /* copy the old block's contents into the new block */
373 memcpy(newp->buf, bc->buf, (size_t)o_blksize);
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
374 newp->dirty = ElvTrue;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
375 bc = newp;
376 }
377
378 /* mark it as being locked */
379 #ifdef DEBUG_SESSION
380 bc->lockfile[bc->locks] = file;
381 bc->lockline[bc->locks] = line;
382 #endif
383 bc->locks++;
384
385 /* NOTE: I'd like to trap cases where a single block is locked
386 * repeatedly. Unfortunately, the recursive nature of the regexp
387 * matcher causes a scanned block to be locked once for each
388 * metacharacter so I can't put a hard limit on it. I'll pretend
389 * I can, and I'll make it a large limit so nobody is likely to
390 * trip it up with a complex regexp.
391 */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
392 assert(bc->locks < MAXLOCKS);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
393
394 /* return the data */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
395 #ifdef LOG_SESSION
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
396 fprintf(stderr, "%s:%d: seslock(...) returning %d\n",
397 file, line, blkno);
398 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
399 return blkno;
400 }
401
402 /* Return a pointer to the start of a block's data in the cache */
403 BLK *sesblk(blkno)
404 _BLKNO_ blkno; /* BLKNO of desired block */
405 {
406 CACHEENTRY *bc;
407
408 bc = findblock(blkno);
409 assert(bc != NULL && bc->locks > 0);
410 return bc->buf;
411 }
412
413
414 /* Release the lock on a block, so that it can be flushed out to the
415 * session file.
416 */
417 void sesunlock(blkno, forwrite)
418 _BLKNO_ blkno; /* BLKNO of block to be unlocked */
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
419 ELVBOOL forwrite; /* if ElvTrue, set the block's "dirty" flag */
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
420 {
421 CACHEENTRY *bc;
422
423 bc = findblock(blkno);
424 assert(bc != NULL && bc->locks > 0 && bc->blkno == blkno);
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
425 if (forwrite)
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
426 bc->dirty = ElvTrue;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
427 bc->locks--;
428 #ifdef DEBUG_SESSION
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
429 bc->lockfile[bc->locks] = NULL;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
430 if (forwrite)
431 {
432 blkwrite(bc->buf, bc->blkno);
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
433 o_blkwrite++;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
434 }
435 #endif
436 }
437
438 /*----------------------------------------------------------------------------*/
439
440 static void flushblock(bc)
441 CACHEENTRY *bc; /* cache item to be flushed */
442 {
443 blkwrite(bc->buf, bc->blkno);
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
444 o_blkwrite++;
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
445 bc->dirty = ElvFalse;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
446 }
447
448 /* If the block is dirty, write it out to the session file. */
449 void sesflush(blkno)
450 _BLKNO_ blkno; /* BLKNO of a block to be flushed */
451 {
452 CACHEENTRY *bc;
453
454 /* find the block */
455 bc = findblock(blkno);
456 assert(bc != NULL && bc->locks == 0);
457
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
458 /* if SES_CHARS or SES_BLKLIST, and not dirty, then don't bother */
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
459 if ((bc->blktype == SES_CHARS || bc->blktype == SES_BLKLIST)
460 && !bc->dirty)
461 {
462 return;
463 }
464
465 flushblock(bc);
466 }
467
468 /* flush every dirty block in the cache */
469 void sessync()
470 {
471 CACHEENTRY *bc;
472
473 safeinspect();
474
475 /* for each block... */
476 for (bc = oldest; bc; bc = bc->newer)
477 {
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
478 #ifdef DEBUG_SESSION
479 if (bc->locks > 0)
480 {
481 int i;
482 for (i = 0; i < QTY(bc->lockfile); i++)
483 {
484 if (!bc->lockfile[i])
485 continue;
486 fprintf(stderr, "in sessync(), lock found from %s:%d\n",
487 bc->lockfile[i], bc->lockline[i]);
488 abort();
489 break;
490 }
491 if (i >= QTY(bc->lockfile))
492 {
493 fprintf(stderr, "in sessync(), %d %s reported but doesn't appear in bc->lockfile[]\n", bc->locks, bc->locks != 1 ? "locks" : "lock");
494 abort();
495 }
496 }
497 #else
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
498 assert(bc->locks == 0);
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
499 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
500
501 /* if dirty, flush it */
502 if (bc->dirty)
503 {
504 flushblock(bc);
505 }
506 }
507
508 /* maybe force the changes out to disk */
509 if (o_sync)
510 {
511 blksync();
512 }
513 }
514
515 /*----------------------------------------------------------------------------*/
516
517
518 /* Allocate a new block (if blkno is 0) or increment the allocation
519 * count on an existing block (if blkno is not 0). Returns its BLKNO.
520 */
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
521 #ifdef DEBUG_SESSION
522 BLKNO _sesalloc(file, line, blkwant, blktype)
523 char *file; /* name of source file that called this func */
524 int line; /* line number of source file */
525 _BLKNO_ blkwant; /* 0 usually, else BLKNO to use */
526 BLKTYPE blktype; /* type of data in this block */
527 #else
528 BLKNO sesalloc(blkwant, blktype)
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
529 _BLKNO_ blkwant; /* 0 usually, else BLKNO to use */
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
530 BLKTYPE blktype; /* type of data in this block */
531 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
532 {
533 BLKNO blkno;
534 int newsize;
535 COUNT *newarray;
536 BLK *tmp;
537 int i;
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
538 #ifdef DEBUG_SESSION
539 BLKTYPE *newtypes;
540 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
541
542 /* if we're supposed to choose a block, then choose one */
543 if (blkwant == 0)
544 {
545 for (blkno = 1; blkno < nblocks && alloccnt[blkno] > 0; blkno++)
546 {
547 }
548 }
549 else
550 {
551 blkno = blkwant;
552 }
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
553 #ifdef DEBUG_SESSION
554 assert(blkno >= nblocks || alloctype[blkno] == SES_NEW
555 || (alloctype[blkno] == SES_CHARS && blktype == SES_CHARS && alloccnt[blkno] > 0));
556 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
557
558 /* if past the end of the current alloccnt array, then grow */
559 if (blkno >= nblocks)
560 {
561 /* reallocate the alloccnt array */
562 newsize = blkno + o_blkgrow - (blkno % o_blkgrow);
563 assert(newsize > blkno);
564 newarray = (COUNT *)safekept(newsize, sizeof(COUNT));
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
565 #ifdef DEBUG_SESSION
566 newtypes = (BLKTYPE *)safekept(newsize, sizeof(BLKTYPE));
567 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
568 for (i = 0; i < nblocks; i++)
569 {
570 newarray[i] = alloccnt[i];
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
571 #ifdef DEBUG_SESSION
572 newtypes[i] = alloctype[i];
573 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
574 }
575 safefree(alloccnt);
576 alloccnt = newarray;
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
577 #ifdef DEBUG_SESSION
578 safefree(alloctype);
579 alloctype = newtypes;
580 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
581 nblocks = newsize;
582
583 /* if new block requested, write dummy data into the session file */
584 if (blkwant == 0)
585 {
586 tmp = (BLK *)safealloc((int)o_blksize, sizeof(char));
587 for (i = blkno; i < nblocks; i++)
588 {
589 blkwrite(tmp, (BLKNO)i);
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
590 o_blkwrite++;
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
591 }
592 safefree(tmp);
593 }
594
595 /* increment the allocation counter for the chosen block */
596 alloccnt[blkno]++;
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
597 #ifdef DEBUG_SESSION
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
598 alloctype[blkno] = blktype;
599 #endif
600
601 #ifdef LOG_SESSION
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
602 fprintf(stderr, "%s:%d: sesalloc(%d, %s), new alloccnt[%d] = %d, nblocks=%d\n",
603 file, line, blkwant, blktypename[blktype],
604 blkno, alloccnt[blkno], nblocks);
605 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
606 }
607 else /* recycling an old block */
608 {
609 /* increment the allocation counter for the chosen block */
610 alloccnt[blkno]++;
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
611 #ifdef DEBUG_SESSION
612 if (alloccnt[blkno] > 10)
613 fprintf(stderr, "sesalloc: allocccnt[%d]=%d, type=%s, called from %s:%d\n",
614 blkno, alloccnt[blkno], blktypename[blktype], file, line);
615 alloctype[blkno] = blktype;
616 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
617
618 /* if block is supposed to be new, then zero it */
619 if (blkwant == 0)
620 {
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
621 (void)seslock(blkno, ElvTrue, blktype);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
622 tmp = sesblk(blkno);
623 memset((char *)tmp, 0, (size_t)o_blksize);
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
624 sesunlock(blkno, ElvTrue);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
625 }
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
626
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
627 #ifdef LOG_SESSION
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
628 fprintf(stderr, "%s:%d: sesalloc(%d, %s), recycled alloccnt[%d] = %d\n",
629 file, line, blkwant, blktypename[blktype],
630 blkno, alloccnt[blkno]);
631 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
632 }
633
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
634 assert(alloccnt[blkno] > 0);
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
635 return blkno;
636 }
637
638 /* Decrement the allocation count of a block. If the block's count
639 * is decremented to 0, it becomes available for reuse by sesalloc.
640 */
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
641 #ifdef DEBUG_SESSION
642 void _sesfree(file, line, blkno)
643 char *file; /* source file of call */
644 int line; /* line number of call */
645 _BLKNO_ blkno; /* BLKNO of a block to be returned to free pool */
646 #else
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
647 void sesfree(blkno)
648 _BLKNO_ blkno; /* BLKNO of a block to be returned to free pool */
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
649 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
650 {
651 assert((int)blkno < nblocks && alloccnt[blkno] > 0);
652 alloccnt[blkno]--;
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
653
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
654 #ifdef LOG_SESSION
8d1ac0c @mbert Import Elvis 2.1 (written by Steve Kirkendall)
authored
655 fprintf(stderr, "%s:%d: sesfree(%d), alloccnt[%d]=%d\n",
656 file, line, blkno, blkno, alloccnt[blkno]);
657 #endif
9f1c6f0 @mbert Import Elvis 2.2_0 (written by Steve Kirkendall)
authored
658 #ifdef DEBUG_SESSION
659 if (alloccnt[blkno] == 0)
660 alloctype[blkno] = SES_NEW;
661 #endif
cf92e3b @mbert Import Elvis 2.0 (written by Steve Kirkendall)
authored
662 }
Something went wrong with that request. Please try again.