dbck-cache.c 32.6 KB
Newer Older
Linus Tolke's avatar
Linus Tolke committed
1
/*
David Byers's avatar
David Byers committed
2
 * $Id: dbck-cache.c,v 0.39 1999/05/23 13:05:13 byers Exp $
Per Cederqvist's avatar
Per Cederqvist committed
3
 * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996  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 *
David Byers's avatar
David Byers committed
42
rcsid = "$Id: dbck-cache.c,v 0.39 1999/05/23 13:05:13 byers 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
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
static void
sync_output_header(FILE* fp, char *state, int oformat)
{
    switch (oformat)
    {
    case 0:
        fprintf(fp, "DIRTY\n");
        break;
    case 1:
        fprintf(fp, "DIRTY:%05ld\n", (long)oformat);
        break;
    case 2:
        fprintf(fp, "DIRTY:%05ld\n", (long)oformat);
        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
730
731
        break;
    case 1:
        break;
    default:
732
        restart_kom("Unknown output file format: %ld\n", oformat);
733
734
    }
    
Per Cederqvist's avatar
Per Cederqvist committed
735
736
737

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

765
766
767
768
769
770
771
772
773
    /*
     * 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
774
    {
775
776
777
    case 0:
        break;
    case 1:
David Byers's avatar
David Byers committed
778
    case 2:
779
780
        break;
    default:
781
        restart_kom("Unknown output file format: %ld\n", oformat);
David Byers's avatar
David Byers committed
782
783
    }
    
Per Cederqvist's avatar
Per Cederqvist committed
784
785
786
787
788
789
790
791
792
#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
793
    sync_output_header(fp, "CLEAN", oformat);
Per Cederqvist's avatar
Per Cederqvist committed
794
795
796
    fclose(fp);

#ifdef TIME_SYNC
David Byers's avatar
David Byers committed
797
    kom_log("Sync ready.\n"
Per Cederqvist's avatar
Per Cederqvist committed
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
    	"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),

815
816
817
818
819
	(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
820
821
822
823
824
825
826

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

extern Success
init_cache(void)
{
    FILE *fp = NULL;
David Byers's avatar
David Byers committed
841
    long i;
Per Cederqvist's avatar
Per Cederqvist committed
842
    extern int vflag;		/* from dbck.c */
843
    extern Bool truncated_texts; /* from dbck.c */
David Byers's avatar
David Byers committed
844
845
    long num;
    long data_file_version;
846
    char done, read_text_num, read_conf_num, c;
847
848
849
850
851
852
853
854
855
856
    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
857
858
859
860
861
862
    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
863
	conf_arr[i] = NULL;
David Byers's avatar
David Byers committed
864
    for (i = 0; i < param.max_conf; i++)
David Byers's avatar
David Byers committed
865
	pers_arr[i] = NULL;
David Byers's avatar
David Byers committed
866
    for (i = 0; i < param.max_text; i++)
David Byers's avatar
David Byers committed
867
868
869
	text_arr[i] = NULL;
    
    
Per Cederqvist's avatar
Per Cederqvist committed
870
871
    new_text_file = NULL;
    
Per Cederqvist's avatar
Per Cederqvist committed
872
    if ( (text_file = fopen(param.textfile_name, "rb")) == NULL )
Per Cederqvist's avatar
Per Cederqvist committed
873
    {
Per Cederqvist's avatar
Per Cederqvist committed
874
	perror(param.textfile_name);
875
	restart_kom("ERROR: init_cache: can't open text file %s.\n",
Per Cederqvist's avatar
Per Cederqvist committed
876
		    param.textfile_name);
Per Cederqvist's avatar
Per Cederqvist committed
877
878
    }

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

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

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

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

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

    /*
     * 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
952
    for ( i = 1;
953
          (data_file_version == 0 && i < next_free_num && !feof(fp)) ||
954
955
          (data_file_version == 1 && !done) ||
          (data_file_version == 2 && !done);
956
          i++ )
Per Cederqvist's avatar
Per Cederqvist committed
957
    {
David Byers's avatar
David Byers committed
958
	num = i;
Per Cederqvist's avatar
Per Cederqvist committed
959
	fskipwhite(fp);
David Byers's avatar
David Byers committed
960

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

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

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

	case 'I':
            switch (data_file_version)
1002
            {
1003
            case 0:
1004
1005
                restart_kom("I record in data file version %ld at %lu.\n",
                            data_file_version, (unsigned long)ftell(fp));
1006
1007
                break;
            case 1:
1008
            case 2:
1009
1010
1011
                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));
1012
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
                
                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:
1045
                restart_kom("Unknown input file format: %ld\n",
1046
                            data_file_version);
1047
            }
1048
            break;
David Byers's avatar
David Byers committed
1049
1050
	    
	case 'C':
1051
1052
1053
            switch (data_file_version)
            {
            case 0:
1054
1055
                restart_kom("C record in data file version %ld at %lu.\n",
                            data_file_version, (unsigned long)ftell(fp));
1056
1057
1058
                break;

            case 1:
1059
            case 2:
1060
1061
1062
1063
1064
                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)
1065
                    restart_kom("init_cache(): %s. i == %lu\n", 
1066
1067
1068
1069
1070
1071
                                "fparse_conference failed", i);
                name_list[num] = EMPTY_STRING;
                s_strcpy(&name_list[num], conf_arr[ num ]->name);
                break;

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

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

            case 1:
1086
            case 2:
1087
1088
1089
1090
1091
                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 )
1092
                    restart_kom("init_cache: fparse_person failed. num==%ld\n",
1093
1094
1095
1096
                                num);
                break;

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

            case 1:
1111
            case 2:
1112
1113
1114
1115
1116
1117
1118
1119
1120
                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
1121
                    kom_log("init_cache(): fparse_text_stat failed "
1122
                        "for text %ld.\n%s",
1123
1124
1125
1126
1127
1128
1129
1130
1131
                        num, "Everything remaining is lost.\n");
                    next_text_num = i;
                    read_text_num = 1;
                    truncated_texts = TRUE;
                    done = 1;
                }
                break;

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

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

            case 1:
1168
            case 2:
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
                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 "
1181
1182
1183
                                "file version %ld at %lu.\n",
                                c, data_file_version,
				(unsigned long)ftell(fp));
1184
1185
1186
1187
                }
                break;

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

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

            case 1:
1202
            case 2:
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
                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 "
1225
1226
1227
                                "version %ld at %lu.\n",
                                c, data_file_version,
				(unsigned long)ftell(fp));
1228
1229
1230
1231
                }
                break;

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

	default:
1238
1239
1240
            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
1241
1242
1243
	}
    }

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

David Byers's avatar
David Byers committed
1249
    if (data_file_version == 0)
Per Cederqvist's avatar
Per Cederqvist committed
1250
    {
1251
        if ( vflag )
David Byers's avatar
David Byers committed
1252
            kom_log("Reading %d persons, starting at pos %lu.\n",
1253
                next_free_num-1, (unsigned long)ftell(fp));
David Byers's avatar
David Byers committed
1254
	for ( i = 1; i < next_free_num; i++ ) /* PERSONS */
Per Cederqvist's avatar
Per Cederqvist committed
1255
	{
David Byers's avatar
David Byers committed
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
	    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 )
1266
		    restart_kom("init_cache: fparse_person failed. i == %ld\n",
David Byers's avatar
David Byers committed
1267
1268
1269
				i);
		break;
	    }
Per Cederqvist's avatar
Per Cederqvist committed
1270
1271
	}

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

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

David Byers's avatar
David Byers committed
1279
	for ( i = 1; i < next_text_num; i++ ) /* TEXT_STATS */
Per Cederqvist's avatar
Per Cederqvist committed
1280
	{
David Byers's avatar
David Byers committed
1281
1282
	    fskipwhite(fp);
	    switch(getc(fp))
1283
	    {
David Byers's avatar
David Byers committed
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
	    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
1296
		    kom_log("init_cache(): fparse_text_stat failed for text %ld.\n"
1297
			"All remaining texts are lost.\n", i);
David Byers's avatar
David Byers committed
1298
1299
1300
1301
		    next_text_num = i;
		    truncated_texts = TRUE;
		}
		break;
1302
	    }
Per Cederqvist's avatar
Per Cederqvist committed
1303
	}
David Byers's avatar
David Byers committed
1304
    } /* if (datafile_version == 0) */
Per Cederqvist's avatar
Per Cederqvist committed
1305

David Byers's avatar
David Byers committed
1306
    kom_log("Read %d confs/persons and %ld texts, eof at %lu\n",
1307
	next_free_num-1, next_text_num-1, (unsigned long)ftell(fp));
Per Cederqvist's avatar
Per Cederqvist committed
1308

David Byers's avatar
David Byers committed
1309
1310
    if (read_text_num == 0 || read_conf_num == 0)
      restart_kom("init_cache(): Failed to read next_conf or text num.\n");
Per Cederqvist's avatar
Per Cederqvist committed
1311
1312
1313
1314
    fclose(fp);

    return OK;
}