dbck-cache.c 32.7 KB
Newer Older
Linus Tolke's avatar
Linus Tolke committed
1
/*
2
 * $Id: dbck-cache.c,v 0.42 1999/05/24 14:28:57 ceder Exp $
3
 * Copyright (C) 1991-1999  Lysator Academic Computer Association.
Linus Tolke's avatar
Linus Tolke committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 *
 * This file is part of the LysKOM server.
 * 
 * LysKOM is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 1, or (at your option) 
 * any later version.
 * 
 * LysKOM is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with LysKOM; see the file COPYING.  If not, write to
 * Lysator, c/o ISY, Linkoping University, S-581 83 Linkoping, SWEDEN,
 * or the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, 
 * MA 02139, USA.
 *
 * Please mail bug reports to bug-lyskom@lysator.liu.se. 
 */
Per Cederqvist's avatar
Per Cederqvist committed
25
26
27
28
29
30
31
32
33
34
/*
 * This module contains some very simple simulations of the routines in
 * cache.c.
 *
 * Extracted from ram-cache.c and rewritten by ceder.
 *
 * New database format with texts in their own file by Inge Wallin.
 *   Also save time as a time_t instead of a struct tm.
 */

David Byers's avatar
David Byers committed
35
36
37
38
39
40

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif


Per Cederqvist's avatar
Per Cederqvist committed
41
static const char *
42
rcsid = "$Id: dbck-cache.c,v 0.42 1999/05/24 14:28:57 ceder Exp $";
43
44
#include "rcs.h"
USE(rcsid);
Per Cederqvist's avatar
Per Cederqvist committed
45

Per Cederqvist's avatar
Per Cederqvist committed
46
#include <stdio.h>
Per Cederqvist's avatar
Per Cederqvist committed
47
#ifndef SEEK_END
Per Cederqvist's avatar
Per Cederqvist committed
48
#  include <fcntl.h>
Per Cederqvist's avatar
Per Cederqvist committed
49
50
#endif
#ifndef SEEK_END
Per Cederqvist's avatar
Per Cederqvist committed
51
52
53
54
55
#  include <unistd.h>
#endif
#ifndef SEEK_END
#  define SEEK_SET 0
#  define SEEK_END 2
Per Cederqvist's avatar
Per Cederqvist committed
56
#endif
Per Cederqvist's avatar
Per Cederqvist committed
57
58
59
#ifdef HAVE_STDLIB_H
#  include <stdlib.h>
#endif
Per Cederqvist's avatar
Per Cederqvist committed
60
#include <time.h>
Per Cederqvist's avatar
Per Cederqvist committed
61
#include <sys/types.h>
Per Cederqvist's avatar
Per Cederqvist committed
62
63
64
#ifdef TIME_SYNC
#  include <sys/resource.h>
#endif
65
66
67
#ifdef HAVE_STDARG_H
#  include <stdarg.h>
#endif
Per Cederqvist's avatar
Per Cederqvist committed
68

69
#include "ldifftime.h"
Per Cederqvist's avatar
Per Cederqvist committed
70
71
#include "exp.h"
#include "misc-types.h"
72
#include "s-string.h"
Per Cederqvist's avatar
Per Cederqvist committed
73
74
#include "kom-types.h"
#include "kom-errno.h"
Per Cederqvist's avatar
Per Cederqvist committed
75
#include "cache.h"
Per Cederqvist's avatar
Per Cederqvist committed
76
77
78
#include "debug.h"
#include "server/smalloc.h"
#include "log.h"
Per Cederqvist's avatar
Per Cederqvist committed
79
#include "lyskomd.h"
Per Cederqvist's avatar
Per Cederqvist committed
80
#include "kom-memory.h"
Per Cederqvist's avatar
Per Cederqvist committed
81
82
#include "ram-parse.h"
#include "ram-output.h"
Per Cederqvist's avatar
Per Cederqvist committed
83
#include "param.h"
Per Cederqvist's avatar
Per Cederqvist committed
84
#include "dbck-cache.h"
85
#include "local-to-global.h"
86
#include "unused.h"
Per Cederqvist's avatar
Per Cederqvist committed
87

Per Cederqvist's avatar
Per Cederqvist committed
88
89
90
91
/*
 * All functions that can fail sets kom_errno to a suitable value
 * if they fail.
 */
Per Cederqvist's avatar
Per Cederqvist committed
92

David Byers's avatar
David Byers committed
93
94
95
Person		** pers_arr;
Conference 	** conf_arr;
String		 * name_list; /* "cache" list */
Per Cederqvist's avatar
Per Cederqvist committed
96
97
98
			        	  /* Global var auto init to NULL */
int		  next_free_num = 1;

David Byers's avatar
David Byers committed
99
Text_stat 	** text_arr;
Per Cederqvist's avatar
Per Cederqvist committed
100
static Text_no next_text_num = 1;
Per Cederqvist's avatar
Per Cederqvist committed
101

102
103
104
/* Defined in standalone.c */

extern Info kom_info;
David Byers's avatar
David Byers committed
105
106


Per Cederqvist's avatar
Per Cederqvist committed
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
/* Defined in ramkomd.c */

static FILE          *text_file = NULL;
static FILE	     *new_text_file = NULL; /* Used when garbage collecting. */

BUGDECL;


/* Macros */

#define TRACE2(format, arg) if ( buglevel > 2 ) printf(format, arg)
#define TRACE1(format) if ( buglevel > 2 ) printf(format)
#define TRACESTR(str)  if ( buglevel > 2 ) s_puts(str)
#define INRANGE(str, num, retval) if ( num == 0 || num >= next_free_num ) \
{			\
    return retval;	\
    printf("%s: conf_no %d out of range 1 ... %d ", str, num, next_free_num); \
    fflush(stdout);	\
    fflush(stderr);	\
    abort();		\
}

#define TEXT_RANGE(str, num, retval) if ( num == 0 || num >= next_text_num ) \
{	\
    return retval;\
Per Cederqvist's avatar
Per Cederqvist committed
132
    printf("Text_no out of range 1 ... %ld ", next_text_num); \
Per Cederqvist's avatar
Per Cederqvist committed
133
134
135
136
137
138
    printf(str);	\
    fflush(stdout);	\
    fflush(stderr);	\
    abort(); 		\
}

Per Cederqvist's avatar
Per Cederqvist committed
139
140
141
#define VOID_TEXT_RANGE(str, num) if ( num == 0 || num >= next_text_num ) \
{	\
    return;\
Per Cederqvist's avatar
Per Cederqvist committed
142
    printf("Text_no out of range 1 ... %ld ", next_text_num); \
Per Cederqvist's avatar
Per Cederqvist committed
143
144
145
146
147
148
    printf(str);	\
    fflush(stdout);	\
    fflush(stderr);	\
    abort(); 		\
}

Per Cederqvist's avatar
Per Cederqvist committed
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

extern Conf_type
cached_get_conf_type (Conf_no conf_no)
{
    return conf_arr [ conf_no ]->type;
}



#define IMPL(retval) if (1) { fflush(stderr); fflush(stdout); abort(); }


/*
 * Various function calls to tell the cache that something is changed.
 */

void
mark_person_as_changed(Pers_no	pers_no)
{
    TRACE2("Person %d is changed\n", pers_no);
    return;    
}


void
mark_conference_as_changed(Conf_no	conf_no)
{
    TRACE2("Conf.  %d is changed\n", conf_no);
    return;
}

void
mark_text_as_changed( Text_no text_no )
{
183
    TRACE2("Text %lu is changed.\n", text_no);
Per Cederqvist's avatar
Per Cederqvist committed
184
    VOID_TEXT_RANGE("mark_text_as_changed\n", text_no);
Per Cederqvist's avatar
Per Cederqvist committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
}    


/*
 * Person-related calls
 */


extern Success
cached_create_person( Pers_no person )
{
    TRACE2("Person %d is being created.\n", person);
    INRANGE("cached_create_person\n", person, FAILURE);

    if ( pers_arr[ person ] != NULL )
    {
	TRACE1("pers_arr not NULL");
	fflush(stdout);
	fflush(stderr);
	abort();
    }
    
    pers_arr[ person ] = alloc_person();
    return OK;
}


extern Person *
cached_get_person_stat( Pers_no	person )
{
    INRANGE("cached_get_person_stat\n", person, NULL);
    TRACE2("cached_get_person_stat %d\n", person);
217
    err_stat = person;
Per Cederqvist's avatar
Per Cederqvist committed
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
    kom_errno = KOM_UNDEF_PERS;
    
    return pers_arr[ person ];
}



/*
 * Conference-related calls
 */
extern Conf_no	/* Also cache the name */
cached_create_conf (String  name)
{
    Conference * conf_c;
    Conf_no	 conf_no;

    TRACE1("cached_create_conf( ");
    TRACESTR(name);
    TRACE1(" )\n");

David Byers's avatar
David Byers committed
238
    if ( next_free_num >= param.max_conf )
Per Cederqvist's avatar
Per Cederqvist committed
239
    {
240
        err_stat = next_free_num;
Per Cederqvist's avatar
Per Cederqvist committed
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
	kom_errno = KOM_INDEX_OUT_OF_RANGE;
	return 0;
    }
    
    conf_no = next_free_num++;
    conf_c  = alloc_conference();

    conf_c->name = EMPTY_STRING;
    s_strcpy(&conf_c->name, name);

    TRACE2(" number %d\n", conf_no);

    conf_arr[ conf_no ] = conf_c;
    pers_arr[ conf_no ] = NULL;
    
    return conf_no;
}

extern Success
cached_delete_conf( Conf_no	conf )
{
    INRANGE("cached_delete_conf()", conf, FAILURE);
    if ( conf_arr[ conf ] == NULL )
    {
265
        err_stat = conf;
Per Cederqvist's avatar
Per Cederqvist committed
266
267
268
269
270
271
272
273
274
275
276
277
278
279
	kom_errno = KOM_UNDEF_CONF;
	return FAILURE;
    }
    free_conference(conf_arr[ conf ]);
    conf_arr[ conf ] = NULL;
    return OK;
}

Success
cached_delete_person(Pers_no pers)
{
    INRANGE("cached_delete_person()", pers, FAILURE);
    if ( pers_arr[ pers ] == NULL )
    {
280
        err_stat = pers;
Per Cederqvist's avatar
Per Cederqvist committed
281
282
283
284
285
286
287
288
289
290
291
292
293
294
	kom_errno = KOM_UNDEF_PERS;
	return FAILURE;
    }

    pers_arr[ pers ] = NULL;
    return OK;
}

Success
cached_delete_text(Text_no text)
{
    TEXT_RANGE("cached_delete_text()", text, FAILURE);
    if ( text_arr[ text ] == NULL )
    {
295
        err_stat = text;
Per Cederqvist's avatar
Per Cederqvist committed
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
	kom_errno = KOM_NO_SUCH_TEXT;
	return FAILURE;
    }
    free_text_stat(text_arr[ text ]);
    text_arr[ text ] = NULL;
    return OK;
    
}


extern Conference *
cached_get_conf_stat(	Conf_no		conf_no )
{
    INRANGE("cached_get_conf_stat\n", conf_no, NULL);
    TRACE2("cached_get_conf_stat %d\n", conf_no);
    kom_errno = KOM_UNDEF_CONF;
312
    err_stat = conf_no;
Per Cederqvist's avatar
Per Cederqvist committed
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
    
    return conf_arr[ conf_no ];
}

/*
 * Return TRUE if conf_no exists.
 */
Bool
cached_conf_exists(Conf_no conf_no)
{
    return conf_arr[ conf_no ] != NULL ? TRUE : FALSE;
}

    
/*
 * Calls to handle texts
 */

extern String
cached_get_text( Text_no text )
{
    String  the_string;

    TEXT_RANGE("cached_get_text\n", text, EMPTY_STRING);
337
    TRACE2("cached_get_text %lu\n", text);
Per Cederqvist's avatar
Per Cederqvist committed
338
339
340
341
342
343
344
345
346

    if ( text_arr[ text ] == NULL )
	return EMPTY_STRING;
    else
    {
	the_string.string = tmp_alloc( text_arr[text]->no_of_chars );
	the_string.len = text_arr[text]->no_of_chars;
	fseek(text_file, text_arr[ text ]->file_pos, SEEK_SET);
	if ( fread(the_string.string, sizeof(char), the_string.len, text_file)
David Byers's avatar
David Byers committed
347
	    != (size_t)the_string.len )
Per Cederqvist's avatar
Per Cederqvist committed
348
	{
David Byers's avatar
David Byers committed
349
	    kom_log("%s read enough characters of text %lu\n",
Per Cederqvist's avatar
Per Cederqvist committed
350
		"WARNING: cached_get_text: couldn't",
351
		(unsigned long)text);
Per Cederqvist's avatar
Per Cederqvist committed
352
353
354
355
356
357
358
359
360
361
	}
		    
	return the_string;
    }
}

extern Text_stat *	/* NULL on error */
cached_get_text_stat(	Text_no		text )
{
    kom_errno = KOM_NO_SUCH_TEXT;
362
    err_stat = text;
Per Cederqvist's avatar
Per Cederqvist committed
363
    TEXT_RANGE("cached_get_text_stat\n", text, NULL);
364
    TRACE2("cached_get_text_stat %lu\n", text);
Per Cederqvist's avatar
Per Cederqvist committed
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
    
    return text_arr[ text ];
}



/*
 * The text is set up with an empty misc-field. The misc field is
 * later initialized by create_text.
 */

#if 0
extern Text_no
cached_create_text( String message)
{
    Text_no tno;

    tno = next_text_num++;

    TRACE2("cached_create_text (len=%d)\n", message.len);

David Byers's avatar
David Byers committed
386
    if ( tno >= param.max_text )
Per Cederqvist's avatar
Per Cederqvist committed
387
    {
David Byers's avatar
David Byers committed
388
	next_text_num = param.max_text;
389
390
	kom_errno = KOM_INDEX_OUT_OF_RANGE;
        err_stat = next_text_num;
Per Cederqvist's avatar
Per Cederqvist committed
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
	
	return 0;
    }
        
    text_arr[ tno ] = alloc_text_stat();
    text_arr[ tno ]->no_of_misc = 0;
    text_arr[ tno ]->misc_items = NULL;
    text_arr[ tno ]->no_of_marks = 0;
    text_arr[ tno ]->no_of_lines = 0;
    text_arr[ tno ]->no_of_chars = 0;
    fseek(text_file, 0, SEEK_END);
    text_arr[ tno ]->file_pos = ftell(text_file);

    if ( fwrite(message.string, sizeof(char), message.len, text_file)
	!= message.len ) {
David Byers's avatar
David Byers committed
406
	kom_log("WARNING: cached_create_text: Couldn't write the text %d\n",
Per Cederqvist's avatar
Per Cederqvist committed
407
408
409
410
411
412
413
414
415
416
417
	    tno);
    }

    fflush(text_file);
    
    TRACE2("cached_create_text -> %d\n", tno);
    
    return tno;
}
#endif

Per Cederqvist's avatar
Per Cederqvist committed
418
void
Per Cederqvist's avatar
Per Cederqvist committed
419
420
421
422
423
cached_flush_text(Text_no text_no,
		  String message)
{
    if ( text_no >= next_text_num )
    {
David Byers's avatar
David Byers committed
424
	kom_log("cached_flush_text(%lu, string): only text %lu exists.",
Per Cederqvist's avatar
Per Cederqvist committed
425
426
427
428
429
430
431
432
	    (u_long) text_no, (u_long) next_text_num);
	return;
    }
        
    fseek(new_text_file, 0, SEEK_END);
    text_arr[ text_no ]->file_pos = ftell(new_text_file);

    if ( fwrite(message.string, sizeof(char), message.len, new_text_file)
David Byers's avatar
David Byers committed
433
	!= (size_t)message.len )
Per Cederqvist's avatar
Per Cederqvist committed
434
    {
David Byers's avatar
David Byers committed
435
	kom_log("WARNING: cached_flush_text: Couldn't write the text %ld\n",
436
	    (unsigned long)text_no);
Per Cederqvist's avatar
Per Cederqvist committed
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
    }

    fflush(new_text_file);
}

Text_no
traverse_text(Text_no seed)
{
    seed++;
    
    while ( seed < next_text_num && text_arr[ seed ] == NULL )
	seed++;

    return (seed == next_text_num) ? 0 : seed ;
}

Pers_no
traverse_person(Pers_no seed)
{
    seed++;
    
    while ( seed < next_free_num && pers_arr[ seed ] == NULL )
	seed++;

    return (seed == next_free_num) ? 0 : seed ;
}

Conf_no
traverse_conference(Conf_no seed)
{
    seed++;
    
    while ( seed < next_free_num && conf_arr[ seed ] == NULL )
	seed++;

    return (seed == next_free_num) ? 0 : seed ;
}

extern Garb_nice
cached_get_garb_nice (Conf_no conf_no)
{
    return conf_arr [ conf_no ]->nice;
}

extern Local_text_no
cached_get_highest_local_no (Conf_no conf_no)
{
484
    return l2g_first_appendable_key(&conf_arr[conf_no]->texts) - 1;
Per Cederqvist's avatar
Per Cederqvist committed
485
486
487
488
}

/* Lock a person struct in memory. Increase a referenc count. */
void
489
cached_lock_person(Pers_no UNUSED(pers_no))
Per Cederqvist's avatar
Per Cederqvist committed
490
491
492
493
{}

/* Decrease reference count. If zero, unlock person. */
void
494
cached_unlock_person(Pers_no UNUSED(pers_no))
Per Cederqvist's avatar
Per Cederqvist committed
495
496
497
498
{}

/* Lock a conf struct in memory. Increase a referenc count. */
void
499
cached_lock_conf(Conf_no UNUSED(conf_no))
Per Cederqvist's avatar
Per Cederqvist committed
500
501
502
503
{}

/* Decrease reference count. If zero, unlock conf. */
void
504
cached_unlock_conf(Conf_no UNUSED(conf_no))
Per Cederqvist's avatar
Per Cederqvist committed
505
506
507
{}


David Byers's avatar
David Byers committed
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
static long
get_version(const char *fn)
{
    FILE	 *fp;
    char	  c;
    long	  version;
    
    if ( (fp = fopen(fn, "rb")) == NULL)
	return -1;

    fseek(fp, 5, SEEK_SET);
    if ( (c = getc(fp)) == '\n')
    {
	fclose(fp);
	return 0;
    }
    version = fparse_long(fp);
    fclose(fp);

    return version;
}
Per Cederqvist's avatar
Per Cederqvist committed
529
530
531
532
533
534
535
536
537
538


static Bool
is_clean(const char *fn)
{
    FILE *fp;

    if ( (fp = fopen(fn, "rb")) == NULL )
	return FALSE;

David Byers's avatar
David Byers committed
539
540
541
542
543
    if ( getc(fp) == 'C' && 
         getc(fp) == 'L' &&
         getc(fp) == 'E' &&
         getc(fp) == 'A' &&
         getc(fp) == 'N' )
Per Cederqvist's avatar
Per Cederqvist committed
544
545
546
547
548
549
550
551
552
553
554
    {
	fclose(fp);
	return TRUE;
    }
    else
    {
	fclose(fp);
	return FALSE;
    }
}

David Byers's avatar
David Byers committed
555
static void
556
sync_output_header(FILE* fp, const char *state, int oformat)
David Byers's avatar
David Byers committed
557
558
559
560
{
    switch (oformat)
    {
    case 0:
561
        fprintf(fp, "%s\n", state);
David Byers's avatar
David Byers committed
562
563
        break;
    case 1:
564
        fprintf(fp, "%s:%05ld\n", state, (long)oformat);
David Byers's avatar
David Byers committed
565
566
        break;
    case 2:
567
        fprintf(fp, "%s:%05ld\n", state, (long)oformat);
David Byers's avatar
David Byers committed
568
569
570
571
572
573
574
575
576
577
        fprintf(fp, "%020lu\n", (unsigned long)time(NULL));
        break;
    default:
        restart_kom("sync_output_header(): Unknown output format %d",
                    oformat);
    }
}



Per Cederqvist's avatar
Per Cederqvist committed
578
579
580
581
582
583
584
585
586
587
#ifdef TIME_SYNC
static long
timerdiff(struct timeval a,
	   struct timeval b)
{
    return a.tv_sec - b.tv_sec;
}
#endif

extern void			/* Write out everything. */
588
cache_sync_all(void)
Per Cederqvist's avatar
Per Cederqvist committed
589
590
{
    FILE *fp;
David Byers's avatar
David Byers committed
591
    long i;
Per Cederqvist's avatar
Per Cederqvist committed
592
593
594
595
596
597
598
599
600
601
602
603
604

#ifdef TIME_SYNC
    struct rusage start, after_confs, after_persons, after_text_stats,
    	after_text_masses;
    time_t st, ac, ap, ats, atm;
    void getrusage(int who, struct rusage *rusage);
#endif
    
#ifdef TIME_SYNC
    getrusage(0, &start);
    time(&st);
#endif

Per Cederqvist's avatar
Per Cederqvist committed
605
    if ( is_clean(param.datafile_name) )
Per Cederqvist's avatar
Per Cederqvist committed
606
    {
607
608
609
610
611
	if (is_clean(param.backupfile_name))
	{
	    if (rename(param.backupfile_name,
		       param.backupfile_name_2) != 0)
	    {
David Byers's avatar
David Byers committed
612
		kom_log("pre_sync: can't do extra backup.\n");
613
614
615
	    }
	}

Per Cederqvist's avatar
Per Cederqvist committed
616
	if ( rename(param.datafile_name, param.backupfile_name) != 0 )
David Byers's avatar
David Byers committed
617
	    kom_log("WARNING: cache_sync_all: can't backup.\n");
Per Cederqvist's avatar
Per Cederqvist committed
618
619
    }
    else
David Byers's avatar
David Byers committed
620
	kom_log("cache_sync_all: datafile not clean. No backup taken.\n");
Per Cederqvist's avatar
Per Cederqvist committed
621
    
Per Cederqvist's avatar
Per Cederqvist committed
622
    if ( (fp=fopen(param.datafile_name, "w") ) == NULL )
Per Cederqvist's avatar
Per Cederqvist committed
623
    {
David Byers's avatar
David Byers committed
624
	kom_log("WARNING: cache_sync_all: can't open file to save in.\n");
Per Cederqvist's avatar
Per Cederqvist committed
625
626
627
	return;
    }

628
629
630
    /*
     * Print file header and other things that go before the conferences.
     */
Per Cederqvist's avatar
Per Cederqvist committed
631

632
633
634
    switch (oformat)
    {
    case 0:
David Byers's avatar
David Byers committed
635
        sync_output_header(fp, "DIRTY", oformat);
David Byers's avatar
David Byers committed
636
	fprintf(fp, "%d\n", next_free_num);	  /* NEXT_FREE_NUM */
637
638
        break;
    case 1:
David Byers's avatar
David Byers committed
639
640
    case 2:
        sync_output_header(fp, "DIRTY", oformat);
David Byers's avatar
David Byers committed
641
	fprintf(fp, "#C %d\n", next_free_num);
Per Cederqvist's avatar
Per Cederqvist committed
642
	fprintf(fp, "#T %ld\n", next_text_num);
643
644
645
        fprintf(fp, "I");
        foutput_info(fp, &kom_info);
        fprintf(fp, "\n");
646
647
        break;
    default:
648
        restart_kom("Unknown output file format: %ld\n", oformat);
649
650
    }
    
Per Cederqvist's avatar
Per Cederqvist committed
651
652
    for ( i = 1; i < next_free_num; i++ ) /* CONFS */
    {
653
654
655
656
657
658
659
660
        switch (oformat)
        {
        case 0:
            if ( conf_arr[ i ] == NULL)
                fprintf(fp, "@");
            else
            {
                fprintf(fp, "+ ");
661
                foutput_conference(fp, conf_arr[ i ]);
662
663
664
665
            }
            putc('\n', fp);
            break;
        case 1:
David Byers's avatar
David Byers committed
666
        case 2:
667
668
            if ( conf_arr[ i ] != NULL )
            {
669
                fprintf(fp, "C %lu", i);
670
671
672
673
674
675
                foutput_conference(fp, conf_arr[ i ]);
                putc('\n', fp);
            }
            break;

        default:
676
            restart_kom("Bad output file format: %ld\n", oformat);
677
        }
Per Cederqvist's avatar
Per Cederqvist committed
678
679
680
681
682
683
684
    }
#ifdef TIME_SYNC
    getrusage(0, &after_confs);
    time(&ac);
#endif
    for ( i = 1; i < next_free_num; i++ ) /* PERSONS */
    {
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
        switch (oformat)
        {
        case 0:
            if ( pers_arr[ i ] == NULL)
                fprintf(fp, "@");
            else
            {
                fprintf(fp, "+ ");
                fprintf(fp, "%dH", PASSWD_LEN);
                fwrite(pers_arr[i]->pwd, PASSWD_LEN, 1, fp);
                foutput_person(fp, pers_arr[ i ]);
            }
            putc('\n', fp);
            break;
        case 1:
David Byers's avatar
David Byers committed
700
        case 2:
701
702
            if ( pers_arr[ i ] != NULL )
            {
703
                fprintf(fp, "P %lu", i);
704
705
706
707
708
709
710
711
                fprintf(fp, " %dH", PASSWD_LEN);
                fwrite(pers_arr[i]->pwd, PASSWD_LEN, 1, fp);
                foutput_person(fp, pers_arr[ i ]);
                putc('\n', fp);
            }
            break;

        default:
712
            restart_kom("Bad output file format: %ld\n", oformat);
713
        }
Per Cederqvist's avatar
Per Cederqvist committed
714
715
716
717
718
719
    }
#ifdef TIME_SYNC
    getrusage(0, &after_persons);
    time(&ap);
#endif

720
721
722
723
724
725
726
    /*
     * Print things that go between persons and texts
     */

    switch (oformat)
    {
    case 0:
Per Cederqvist's avatar
Per Cederqvist committed
727
	fprintf(fp, "%ld\n", next_text_num);	/* NEXT_TEXT_NUM */
728
729
        break;
    case 1:
730
    case 2:
731
732
        break;
    default:
733
        restart_kom("Unknown output file format: %ld\n", oformat);
734
735
    }
    
Per Cederqvist's avatar
Per Cederqvist committed
736
737
738

    for ( i = 1; i < next_text_num; i++ ) /* TEXT_STATS */
    {
739
740
741
742
743
744
745
746
747
748
749
750
751
        switch (oformat)
        {
        case 0:
            if ( text_arr[ i ] == NULL )
                fprintf(fp, "@");
            else
            {
                fprintf(fp, "+ ");
                foutput_text_stat(fp, text_arr[ i ]);
            }
            putc('\n', fp);
            break;
        case 1:
David Byers's avatar
David Byers committed
752
        case 2:
753
754
            if ( text_arr[ i ] != NULL )
            {
755
                fprintf(fp, "T %lu", i);
756
757
758
759
760
                foutput_text_stat(fp, text_arr[ i ]);
                putc('\n', fp);
            }
            break;
        default:
761
            restart_kom("Unknown output file format: %ld\n", oformat);
762
763
                
        }
Per Cederqvist's avatar
Per Cederqvist committed
764
765
    }

766
767
768
769
770
771
772
773
774
    /*
     * Print file footer
     *
     * Ho-hum. I thought there was supposed to be a newline at the end
     * of a version zero file, but it seems I was wrong, so this code
     * basically does...absolutely nothing.
     */

    switch (oformat)
David Byers's avatar
David Byers committed
775
    {
776
777
778
    case 0:
        break;
    case 1:
David Byers's avatar
David Byers committed
779
    case 2:
780
781
        break;
    default:
782
        restart_kom("Unknown output file format: %ld\n", oformat);
David Byers's avatar
David Byers committed
783
784
    }
    
Per Cederqvist's avatar
Per Cederqvist committed
785
786
787
788
789
790
791
792
793
#ifdef TIME_SYNC
    getrusage(0, &after_text_stats);
    time(&ats);

    getrusage(0, &after_text_masses);
    time(&atm);
#endif

    rewind(fp);
David Byers's avatar
David Byers committed
794
    sync_output_header(fp, "CLEAN", oformat);
Per Cederqvist's avatar
Per Cederqvist committed
795
796
797
    fclose(fp);

#ifdef TIME_SYNC
David Byers's avatar
David Byers committed
798
    kom_log("Sync ready.\n"
Per Cederqvist's avatar
Per Cederqvist committed
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
    	"User: %4ld sec (%4ld conf, %4ld pers, %4ld stat, %4ld text)\n"
    	"Sys:  %4ld sec (%4ld conf, %4ld pers, %4ld stat, %4ld text)\n"
	"Real: %4ld sec (%4ld conf, %4ld pers, %4ld stat, %4ld text)\n"
	"Page faults: %4ld. Swapped: %4ld. Outblocked: %4ld.\n",
	
	timerdiff(after_text_masses.ru_utime, start.ru_utime),
	timerdiff(after_confs.ru_utime, start.ru_utime),
	timerdiff(after_persons.ru_utime, after_confs.ru_utime),
	timerdiff(after_text_stats.ru_utime, after_persons.ru_utime),
	timerdiff(after_text_masses.ru_utime, after_text_stats.ru_utime),
	
	timerdiff(after_text_masses.ru_stime, start.ru_stime),
	timerdiff(after_confs.ru_stime, start.ru_stime),
	timerdiff(after_persons.ru_stime, after_confs.ru_stime),
	timerdiff(after_text_stats.ru_stime, after_persons.ru_stime),
	timerdiff(after_text_masses.ru_stime, after_text_stats.ru_stime),

816
817
818
819
820
	(u_long)ldifftime(atm, st),
	(u_long)ldifftime(ac, st),
	(u_long)ldifftime(ap, ac),
	(u_long)ldifftime(ats, ap),
	(u_long)ldifftime(atm, ats),
Per Cederqvist's avatar
Per Cederqvist committed
821
822
823
824
825
826
827

	after_text_masses.ru_majflt - start.ru_majflt,
	after_text_masses.ru_nswap - start.ru_nswap,
	after_text_masses.ru_oublock - start.ru_oublock);
#endif    
}

Per Cederqvist's avatar
Per Cederqvist committed
828
void
Per Cederqvist's avatar
Per Cederqvist committed
829
830
cache_open_new_text_file(void)
{
Per Cederqvist's avatar
Per Cederqvist committed
831
    if ( ( new_text_file = fopen(param.textfile_name, "w")) == NULL )
Per Cederqvist's avatar
Per Cederqvist committed
832
    {
David Byers's avatar
David Byers committed
833
	kom_log("Can't open file to save new texts. Goodbye.\n");
Per Cederqvist's avatar
Per Cederqvist committed
834
835
836
837
838
839
840
841
	exit(1);
    }
}

extern Success
init_cache(void)
{
    FILE *fp = NULL;
David Byers's avatar
David Byers committed
842
    long i;
Per Cederqvist's avatar
Per Cederqvist committed
843
    extern int vflag;		/* from dbck.c */
844
    extern Bool truncated_texts; /* from dbck.c */
David Byers's avatar
David Byers committed
845
846
    long num;
    long data_file_version;
847
    char done, read_text_num, read_conf_num, c;
848
849
850
851
852
853
854
855
856
857
    extern int modifications;
    extern int pers_pres_conf;
    extern int conf_pres_conf;
    extern int motd_conf;
    extern int motd_of_lyskom;
    extern int kom_news_conf;
       
    read_text_num = 0;
    read_conf_num = 0;
        
David Byers's avatar
David Byers committed
858
859
860
861
862
863
    pers_arr = smalloc(sizeof(*pers_arr) * param.max_conf);
    conf_arr = smalloc(sizeof(*conf_arr) * param.max_conf);
    text_arr = smalloc(sizeof(*text_arr) * param.max_text);
    name_list = smalloc(sizeof(*name_list) * param.max_conf);

    for (i = 0; i < param.max_conf; i++)
David Byers's avatar
David Byers committed
864
	conf_arr[i] = NULL;
David Byers's avatar
David Byers committed
865
    for (i = 0; i < param.max_conf; i++)
David Byers's avatar
David Byers committed
866
	pers_arr[i] = NULL;
David Byers's avatar
David Byers committed
867
    for (i = 0; i < param.max_text; i++)
David Byers's avatar
David Byers committed
868
869
870
	text_arr[i] = NULL;
    
    
Per Cederqvist's avatar
Per Cederqvist committed
871
872
    new_text_file = NULL;
    
Per Cederqvist's avatar
Per Cederqvist committed
873
    if ( (text_file = fopen(param.textfile_name, "rb")) == NULL )
Per Cederqvist's avatar
Per Cederqvist committed
874
    {
Per Cederqvist's avatar
Per Cederqvist committed
875
	perror(param.textfile_name);
876
	restart_kom("ERROR: init_cache: can't open text file %s.\n",
Per Cederqvist's avatar
Per Cederqvist committed
877
		    param.textfile_name);
Per Cederqvist's avatar
Per Cederqvist committed
878
879
    }

Per Cederqvist's avatar
Per Cederqvist committed
880
    if ( is_clean(param.datafile_name) )
Per Cederqvist's avatar
Per Cederqvist committed
881
    {
David Byers's avatar
David Byers committed
882
	data_file_version = get_version(param.datafile_name);
Per Cederqvist's avatar
Per Cederqvist committed
883
	if ( (fp = fopen(param.datafile_name, "rb")) == NULL )
Per Cederqvist's avatar
Per Cederqvist committed
884
	{
David Byers's avatar
David Byers committed
885
	    kom_log("WARNING: init_cache: can't open datafile.\n");
Per Cederqvist's avatar
Per Cederqvist committed
886
887
	    return FAILURE;
	}
David Byers's avatar
David Byers committed
888
	kom_log("MSG: init_cache: using datafile.\n");
Per Cederqvist's avatar
Per Cederqvist committed
889
    }
Per Cederqvist's avatar
Per Cederqvist committed
890
    else if ( is_clean(param.backupfile_name) )
Per Cederqvist's avatar
Per Cederqvist committed
891
    {
David Byers's avatar
David Byers committed
892
	data_file_version = get_version(param.backupfile_name);
Per Cederqvist's avatar
Per Cederqvist committed
893
	if ( (fp = fopen(param.backupfile_name, "rb")) == NULL )
Per Cederqvist's avatar
Per Cederqvist committed
894
	{
David Byers's avatar
David Byers committed
895
	    kom_log("WARNING: init_cache: can't open backupfile.\n");
Per Cederqvist's avatar
Per Cederqvist committed
896
897
	    return FAILURE;
	}
David Byers's avatar
David Byers committed
898
	kom_log("MSG: init_cache: using backup file.\n");
Per Cederqvist's avatar
Per Cederqvist committed
899
900
901
    }
    else
    {
David Byers's avatar
David Byers committed
902
	kom_log("WARNING: init_cache: can't find old data base.\n");
Per Cederqvist's avatar
Per Cederqvist committed
903
904
905
	return FAILURE;
    }

906
907
908
909
    /*
     * If no output format has been selected, use the input format
     */

910
911
912
    if (oformat == -1)
        oformat = data_file_version;

913
914
915
    /*
     * Read file header
     */
David Byers's avatar
David Byers committed
916

917
    set_input_format(data_file_version);
918
919
920
921
    switch (data_file_version)
    {
    case 0:
	fseek(fp, 6, SEEK_SET);	/* skip clean/dirty flag. */
David Byers's avatar
David Byers committed
922
923
	next_free_num = fparse_long(fp);	  /* NEXT_FREE_NUM */
	read_conf_num = 1;
924
925
        if (vflag)
        {
David Byers's avatar
David Byers committed
926
927
            kom_log("Data file version is '%ld'\n", data_file_version);
            kom_log("Reading %d conferences, starting at pos %ld.\n",
928
                next_free_num-1, (unsigned long)ftell(fp));
929
930
931
932
933
        }
        break;
    case 1:
	fseek(fp, 12, SEEK_SET);
        if (vflag)
David Byers's avatar
David Byers committed
934
            kom_log("Data file version is '%ld'\n", data_file_version);
935
        break;
David Byers's avatar
David Byers committed
936
937
938
939
940
    case 2:
        fseek(fp, 33, SEEK_SET);
        if (vflag)
            kom_log("Data file version is '%ld'\n", data_file_version);
        break;
941
    default:
942
        restart_kom("Unknown input file format: %ld\n", data_file_version);
943
    }
David Byers's avatar
David Byers committed
944
945
    
    done = 0;
946
947
948
949
950
951
952

    /*
     * Loop over records in the database. For a version zero database,
     * loop next_free_num times and for a version one database, loop
     * until the end of the file or until done is set
     */
    
David Byers's avatar
David Byers committed
953
    for ( i = 1;
954
          (data_file_version == 0 && i < next_free_num && !feof(fp)) ||
955
956
          (data_file_version == 1 && !done) ||
          (data_file_version == 2 && !done);
957
          i++ )
Per Cederqvist's avatar
Per Cederqvist committed
958
    {
David Byers's avatar
David Byers committed
959
	num = i;
Per Cederqvist's avatar
Per Cederqvist committed
960
	fskipwhite(fp);
David Byers's avatar
David Byers committed
961

962
963
964
965
	switch(c = getc(fp))
	{
        case EOF:
            switch (data_file_version)
966
            {
967
968
            case 0:
                restart_kom("Unexpected end-of-file reading conferences "
969
                            "in data file version %ld.",
970
971
972
973
                            data_file_version);
                break;

            case 1:
974
	    case 2:
975
976
977
978
                done = 1;
                break;

            default:
979
                restart_kom("Unknown input file format: %ld\n",
980
                            data_file_version);
981
            }
982
983
984
985
            break;
            
	case '@':
            switch (data_file_version)
986
            {
987
988
989
990
            case 0:
                conf_arr[num] = NULL;
                break;
            case 1:
991
            case 2:
992
993
		restart_kom("@ record in data file version %ld at %lu.\n",
                            data_file_version, (unsigned long)ftell(fp));
994
995
                break;
            default:
996
                restart_kom("Unknown input file format: %ld\n",
997
                            data_file_version);
998
            }
999
1000
1001
1002
            break;

	case 'I':
            switch (data_file_version)
1003
            {
1004
            case 0:
1005
1006
                restart_kom("I record in data file version %ld at %lu.\n",
                            data_file_version, (unsigned long)ftell(fp));
1007
1008
                break;
            case 1:
1009
            case 2:
1010
1011
1012
                if (fparse_info(fp, &kom_info) != OK)
                    restart_kom("Invalid I record in data file version %ld at %lu.\n",
                                data_file_version, (unsigned long)ftell(fp));
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
                
                if (pers_pres_conf != -1)
                {
                    modifications += (kom_info.pers_pres_conf !=
                                      pers_pres_conf);
                    kom_info.pers_pres_conf = pers_pres_conf;
                }
                if (conf_pres_conf != -1)
                {
                    modifications += (kom_info.conf_pres_conf !=
                                      conf_pres_conf);
                    kom_info.conf_pres_conf = conf_pres_conf;
                }
                if (motd_conf != -1)
                {
                    modifications += (kom_info.motd_conf !=
                                      motd_conf);
                    kom_info.motd_conf = motd_conf;
                }
                if (kom_news_conf != -1)
                {
                    modifications += (kom_info.kom_news_conf !=
                                      kom_news_conf);
                    kom_info.kom_news_conf = kom_news_conf;
                }
                if (motd_of_lyskom != -1)
                {
                    modifications += (kom_info.motd_of_lyskom !=
                                      motd_of_lyskom);
                    kom_info.motd_of_lyskom = motd_of_lyskom;
                }
                break;
            default:
1046
                restart_kom("Unknown input file format: %ld\n",
1047
                            data_file_version);
1048
            }
1049
            break;
David Byers's avatar
David Byers committed
1050
1051
	    
	case 'C':
1052
1053
1054
            switch (data_file_version)
            {
            case 0:
1055
1056
                restart_kom("C record in data file version %ld at %lu.\n",
                            data_file_version, (unsigned long)ftell(fp));
1057
1058
1059
                break;

            case 1:
1060
            case 2:
1061
1062
1063
1064
1065
                num = fparse_long(fp);
                if (conf_arr[num])
                    free_conference(conf_arr[num]);
                conf_arr[num] = alloc_conference();
                if (fparse_conference(fp, conf_arr[num]) != OK)
1066
                    restart_kom("init_cache(): %s. i == %lu\n", 
1067
1068
1069
1070
1071
1072
                                "fparse_conference failed", i);
                name_list[num] = EMPTY_STRING;
                s_strcpy(&name_list[num], conf_arr[ num ]->name);
                break;

            default:
1073
                restart_kom("Unknown input file format: %ld\n",
1074
1075
                            data_file_version);
            }
Per Cederqvist's avatar
Per Cederqvist committed
1076
1077
	    break;

David Byers's avatar
David Byers committed
1078
	case 'P':
1079
1080
1081
            switch (data_file_version)
            {
            case 0:
1082
1083
                restart_kom("P record in data file version %ld at %lu.\n",
                            data_file_version, (unsigned long)ftell(fp));
1084
1085
1086
                break;

            case 1:
1087
            case 2:
1088
1089
1090
1091
1092
                num = fparse_long(fp);
                if (pers_arr[num])
                    free_person(pers_arr[num]);
                pers_arr[num] = alloc_person();
                if ( fparse_person(fp, pers_arr[ num ]) != OK )
1093
                    restart_kom("init_cache: fparse_person failed. num==%ld\n",
1094
1095
1096
1097
                                num);
                break;

            default:
1098
                restart_kom("Unknown input file format: %ld\n",
1099
1100
                            data_file_version);
            }
David Byers's avatar
David Byers committed
1101
1102
1103
	    break;
	    
	case 'T':
1104
1105
1106
            switch (data_file_version)
            {
            case 0:
1107
1108
                restart_kom("T record in data file version %ld at %lu\n",
                            data_file_version, (unsigned long)ftell(fp));
1109
1110
1111
                break;

            case 1:
1112
            case 2:
1113
1114
1115
1116
1117
1118
1119
1120
1121
                num = fparse_long(fp);
                if (text_arr[num])
                    free_text_stat(text_arr[num]);
                text_arr[ num ] = alloc_text_stat();
                if ( fparse_text_stat(fp, text_arr[ num ]) != OK )
                {
                    /* Simply ignore everything else.  The cause of this
                       error might be that the file has been truncated (maybe
                       due to an overfull disk). */
David Byers's avatar
David Byers committed
1122
                    kom_log("init_cache(): fparse_text_stat failed "
1123
                        "for text %ld.\n%s",
1124
1125
1126
1127
1128
1129
1130
1131
1132
                        num, "Everything remaining is lost.\n");
                    next_text_num = i;
                    read_text_num = 1;
                    truncated_texts = TRUE;
                    done = 1;
                }
                break;

            default:
1133
                restart_kom("Unknown input file format: %ld\n",
1134
1135
                            data_file_version);
            }
David Byers's avatar
David Byers committed
1136
1137
	    break;	
    
Per Cederqvist's avatar
Per Cederqvist committed
1138
	case '+':
1139
1140
1141
1142
1143
            switch (data_file_version)
            {
            case 0:
                conf_arr[ i ] = alloc_conference();
                if ( fparse_conference(fp, conf_arr[ i ]) != OK )
1144
                    restart_kom("init_cache(): %s. i == %lu\n", 
1145
1146
1147
1148
1149
                                "fparse_conference failed", i);
                name_list[i] = EMPTY_STRING;
                s_strcpy(&name_list[i], conf_arr[ i ]->name);
                break;
            case 1:
1150
            case 2:
1151
1152
                restart_kom("+ record in data file version %ld at %lu.\n",
                            data_file_version, (unsigned long)ftell(fp));
1153
1154
                break;
            default:
1155
                restart_kom("Unknown input file format: %ld\n",
1156
1157
1158
                            data_file_version);
            }
            break;
David Byers's avatar
David Byers committed
1159
1160

	case '#':
1161
1162
1163
            switch (data_file_version)
            {
            case 0:
1164
1165
                restart_kom("#record in data file version %ld at %lu.\n",
                            data_file_version, (unsigned long)ftell(fp));
1166
1167
1168
                break;

            case 1:
1169
            case 2:
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
                switch (c = getc(fp))
                {
                case 'C':
                    next_free_num = fparse_long(fp);
                    read_conf_num = 1;
                    break;
                case 'T':
                    next_text_num = fparse_long(fp);
                    read_text_num = 1;
                    break;
                default:
                    restart_kom("Unknown # record (#%c) in data "
1182
1183
1184
                                "file version %ld at %lu.\n",
                                c, data_file_version,
				(unsigned long)ftell(fp));
1185
1186
1187
1188
                }
                break;

            default:
1189
                restart_kom("Unknown input file format: %ld\n",
1190
                            data_file_version);
David Byers's avatar
David Byers committed
1191
1192
1193
1194
	  }
	  break;

	case '-':
1195
1196
1197
            switch (data_file_version)
            {
            case 0:
1198
1199
                restart_kom("- record in data file version %ld at %lu.\n",
                            data_file_version, (unsigned long)ftell(fp));
1200
1201
1202
                break;

            case 1:
1203
            case 2:
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
                switch(c = getc(fp))
                {
                case 'C':
                    num = fparse_long(fp);
                    if (conf_arr[num] != NULL)
                        free_conference(conf_arr[num]);
                    conf_arr[num] = NULL;
                    break;
                case 'P':
                    num = fparse_long(fp);
                    if (pers_arr[num] != NULL)
                        free_person(pers_arr[num]);
                    pers_arr[num] = NULL;
                    break;
                case 'T':
                    num = fparse_long(fp);
                    if (text_arr[num] != NULL)
                        free_text_stat(text_arr[num]);
                    text_arr[num] = NULL;
                    break;
                default:
                    restart_kom("Unknown - record (%c) in data file "
1226
1227
1228
                                "version %ld at %lu.\n",
                                c, data_file_version,
				(unsigned long)ftell(fp));
1229
1230
1231
1232
                }
                break;

            default:
1233
                restart_kom("Unknown input file format %ld\n",
1234
1235
1236
                            data_file_version);
            }
            break;
David Byers's avatar
David Byers committed
1237
1238

	default:
1239
1240
1241
            restart_kom("Unknown record type in data file version "
			"%ld at %lu.\n",
                        data_file_version, (unsigned long)ftell(fp));
Per Cederqvist's avatar
Per Cederqvist committed
1242
1243
1244
	}
    }

1245
1246
1247
1248
    /*
     * The rest is only for data file version 0
     */
    
Per Cederqvist's avatar
Per Cederqvist committed
1249

David Byers's avatar
David Byers committed
1250
    if (data_file_version == 0)
Per Cederqvist's avatar
Per Cederqvist committed
1251
    {
1252
        if ( vflag )
David Byers's avatar
David Byers committed
1253
            kom_log("Reading %d persons, starting at pos %lu.\n",
1254
                next_free_num-1, (unsigned long)ftell(fp));
David Byers's avatar
David Byers committed
1255
	for ( i = 1; i < next_free_num; i++ ) /* PERSONS */
Per Cederqvist's avatar
Per Cederqvist committed
1256
	{
David Byers's avatar
David Byers committed
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
	    fskipwhite(fp);
	    switch(getc(fp))
	    {
	    case '@':
		pers_arr[ i ] = NULL;
		break;

	    case '+':
		pers_arr[ i ] = alloc_person();
		if ( fparse_person(fp, pers_arr[ i ]) != OK )
1267
		    restart_kom("init_cache: fparse_person failed. i == %ld\n",
David Byers's avatar
David Byers committed
1268
1269
1270
				i);
		break;
	    }
Per Cederqvist's avatar
Per Cederqvist committed
1271
1272
	}

David Byers's avatar
David Byers committed
1273
1274
	next_text_num = fparse_long(fp);	/* NEXT_TEXT_NUM */
	read_text_num = 1;
Per Cederqvist's avatar
Per Cederqvist committed
1275

David Byers's avatar
David Byers committed
1276
	if ( vflag )
David Byers's avatar
David Byers committed
1277
	    kom_log("Reading %ld texts, starting at pos %lu.\n",
1278
		next_text_num-1, (unsigned long)ftell(fp));
Per Cederqvist's avatar
Per Cederqvist committed
1279

David Byers's avatar
David Byers committed
1280
	for ( i = 1; i < next_text_num; i++ ) /* TEXT_STATS */
Per Cederqvist's avatar
Per Cederqvist committed
1281
	{
David Byers's avatar
David Byers committed
1282
1283
	    fskipwhite(fp);
	    switch(getc(fp))
1284
	    {
David Byers's avatar
David Byers committed
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
	    case '@':
		text_arr[ i ] = NULL;
		break;

	    case '+':
		text_arr[ i ] = alloc_text_stat();
		if ( fparse_text_stat(fp, text_arr[ i ]) != OK )
		{
		    /* Simply ignore the following texts.  The cause of this
		       error might be that the file has been truncated (maybe
		       due to an overfull disk). */

David Byers's avatar
David Byers committed
1297
		    kom_log("init_cache(): fparse_text_stat failed for text %ld.\n"
1298
			"All remaining texts are lost.\n", i);
David Byers's avatar
David Byers committed
1299
1300
1301
1302
		    next_text_num = i;
		    truncated_texts = TRUE;
		}
		break;
1303
	    }