2 * Copyright (C) 1994-1995, Index Data I/S
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.3 1995-11-16 15:34:55 adam
8 * Uses new record management system in both indexer and server.
10 * Revision 1.2 1995/11/15 19:13:08 adam
11 * Work on record management.
13 * Revision 1.1 1995/11/15 14:46:20 adam
14 * Started work on better record management system.
47 struct record_cache_entry *record_cache;
50 struct record_cache_entry {
55 struct record_index_entry {
67 #define REC_HEAD_MAGIC "rechead"
69 char *rec_strdup (const char *s)
75 p = malloc (strlen(s)+1);
78 logf (LOG_FATAL|LOG_ERRNO, "malloc");
85 static void rec_write_head (Records p)
90 assert (p->index_fd != -1);
91 if (lseek (p->index_fd, (off_t) 0, SEEK_SET) == -1)
93 logf (LOG_FATAL|LOG_ERRNO, "lseek to 0 in %s", p->index_fname);
96 r = write (p->index_fd, &p->head, sizeof(p->head));
100 logf (LOG_FATAL|LOG_ERRNO, "write head of %s", p->index_fname);
102 case sizeof(p->head):
105 logf (LOG_FATAL, "write head of %s. wrote %d", p->index_fname, r);
110 Records rec_open (int rw)
115 if (!(p = malloc (sizeof(*p))))
117 logf (LOG_FATAL|LOG_ERRNO, "malloc");
123 p->data_fname = "recdata";
125 p->index_fname = "recindex";
126 p->index_fd = open (p->index_fname,
127 rw ? (O_RDWR|O_CREAT) : O_RDONLY, 0666);
128 if (p->index_fd == -1)
130 logf (LOG_FATAL|LOG_ERRNO, "open %s", p->index_fname);
133 r = read (p->index_fd, &p->head, sizeof(p->head));
137 logf (LOG_FATAL|LOG_ERRNO, "read %s", p->index_fname);
140 memcpy (p->head.magic, REC_HEAD_MAGIC, sizeof(p->head.magic));
141 p->head.index_free = 0;
142 p->head.index_last = 1;
143 p->head.no_records = 0;
144 p->head.data_size = 0;
145 p->head.data_slack = 0;
146 p->head.data_used = 0;
150 case sizeof(p->head):
151 if (memcmp (p->head.magic, REC_HEAD_MAGIC, sizeof(p->head.magic)))
153 logf (LOG_FATAL, "read %s. bad header", p->index_fname);
158 logf (LOG_FATAL, "read head of %s. expected %d. got %d",
159 p->index_fname, sizeof(p->head), r);
162 p->data_fd = open (p->data_fname,
163 rw ? (O_RDWR|O_CREAT) : O_RDONLY, 0666);
164 if (p->data_fd == -1)
166 logf (LOG_FATAL|LOG_ERRNO, "open %s", p->data_fname);
171 if (!(p->record_cache = malloc (sizeof(*p->record_cache)*p->cache_max)))
173 logf (LOG_FATAL|LOG_ERRNO, "malloc");
179 static void read_indx (Records p, int sysno, void *buf, int itemsize)
182 off_t pos = (sysno-1)*itemsize + sizeof(p->head);
184 if (lseek (p->index_fd, pos, SEEK_SET) == (pos) -1)
186 logf (LOG_FATAL|LOG_ERRNO, "seek in %s to pos %ld",
187 p->index_fname, (long) pos);
190 r = read (p->index_fd, buf, itemsize);
194 logf (LOG_FATAL|LOG_ERRNO, "read in %s at pos %ld",
195 p->index_fname, (long) pos);
197 logf (LOG_FATAL, "read in %s at pos %ld",
198 p->index_fname, (long) pos);
203 static void rec_write_single (Records p, Record rec)
205 struct record_index_entry entry;
206 int r, i, size = 0, got;
208 off_t pos = (rec->sysno-1)*sizeof(entry) + sizeof(p->head);
210 for (i = 0; i < REC_NO_INFO; i++)
214 size += strlen(rec->info[i])+1;
216 entry.u.used.offset = p->head.data_size;
217 entry.u.used.size = size;
218 p->head.data_size += size;
219 p->head.data_used += size;
221 if (lseek (p->index_fd, pos, SEEK_SET) == (pos) -1)
223 logf (LOG_FATAL|LOG_ERRNO, "seek in %s to pos %ld",
224 p->index_fname, (long) pos);
227 r = write (p->index_fd, &entry, sizeof(entry));
228 if (r != sizeof(entry))
231 logf (LOG_FATAL|LOG_ERRNO, "write of %s at pos %ld",
232 p->index_fname, (long) pos);
234 logf (LOG_FATAL, "write of %s at pos %ld",
235 p->index_fname, (long) pos);
238 if (lseek (p->data_fd, entry.u.used.offset, SEEK_SET) == -1)
240 logf (LOG_FATAL|LOG_ERRNO, "lseek in %s to pos %ld",
241 p->data_fname, entry.u.used.offset);
244 if (p->tmp_size < entry.u.used.size)
247 p->tmp_size = entry.u.used.size + 16384;
248 if (!(p->tmp_buf = malloc (p->tmp_size)))
250 logf (LOG_FATAL|LOG_ERRNO, "malloc");
255 for (i = 0; i < REC_NO_INFO; i++)
260 strcpy (cptr, rec->info[i]);
261 cptr += strlen(rec->info[i]) + 1;
263 for (got = 0; got < entry.u.used.size; got += r)
265 r = write (p->data_fd, p->tmp_buf + got, entry.u.used.size - got);
268 logf (LOG_FATAL|LOG_ERRNO, "write of %s", p->data_fname);
274 static void rec_cache_flush (Records p)
277 for (i = 0; i<p->cache_cur; i++)
279 struct record_cache_entry *e = p->record_cache + i;
281 rec_write_single (p, e->rec);
287 static Record *rec_cache_lookup (Records p, int sysno, int dirty)
290 for (i = 0; i<p->cache_cur; i++)
292 struct record_cache_entry *e = p->record_cache + i;
293 if (e->rec->sysno == sysno)
303 static void rec_cache_insert (Records p, Record rec, int dirty)
305 struct record_cache_entry *e;
307 if (p->cache_cur == p->cache_max)
309 assert (p->cache_cur < p->cache_max);
311 e = p->record_cache + (p->cache_cur)++;
313 e->rec = rec_cp (rec);
316 void rec_close (Records *p)
320 rec_cache_flush (*p);
321 free ((*p)->record_cache);
326 if ((*p)->index_fd != -1)
327 close ((*p)->index_fd);
329 if ((*p)->data_fd != -1)
330 close ((*p)->data_fd);
332 free ((*p)->tmp_buf);
338 Record rec_get (Records p, int sysno)
342 struct record_index_entry entry;
349 if ((recp = rec_cache_lookup (p, sysno, 0)))
350 return rec_cp (*recp);
352 read_indx (p, sysno, &entry, sizeof(entry));
354 if (!(rec = malloc (sizeof(*rec))))
356 logf (LOG_FATAL|LOG_ERRNO, "malloc");
359 if (lseek (p->data_fd, entry.u.used.offset, SEEK_SET) == -1)
361 logf (LOG_FATAL|LOG_ERRNO, "lseek in %s to pos %ld",
362 p->data_fname, entry.u.used.offset);
365 if (p->tmp_size < entry.u.used.size)
368 p->tmp_size = entry.u.used.size + 16384;
369 if (!(p->tmp_buf = malloc (p->tmp_size)))
371 logf (LOG_FATAL|LOG_ERRNO, "malloc");
375 for (got = 0; got < entry.u.used.size; got += r)
377 r = read (p->data_fd, p->tmp_buf + got, entry.u.used.size - got);
380 logf (LOG_FATAL|LOG_ERRNO, "read of %s", p->data_fname);
387 for (i = 0; i < REC_NO_INFO; i++)
390 rec->info[i] = rec_strdup (nptr);
391 nptr += strlen(nptr)+1;
398 rec_cache_insert (p, rec, 0);
402 Record rec_new (Records p)
408 if (!(rec = malloc (sizeof(*rec))))
410 logf (LOG_FATAL|LOG_ERRNO, "malloc");
413 if (p->head.index_free == 0)
414 sysno = (p->head.index_last)++;
417 struct record_index_entry entry;
419 read_indx (p, p->head.index_free, &entry, sizeof(entry));
420 sysno = p->head.index_free;
421 p->head.index_free = entry.u.free.next;
423 (p->head.no_records)++;
425 for (i = 0; i < REC_NO_INFO; i++)
427 rec_cache_insert (p, rec, 1);
431 void rec_put (Records p, Record rec)
435 if ((recp = rec_cache_lookup (p, rec->sysno, 1)))
438 *recp = rec_cp (rec);
441 rec_cache_insert (p, rec, 1);
444 void rec_rm (Record rec)
447 for (i = 0; i < REC_NO_INFO; i++)
452 Record rec_cp (Record rec)
457 if (!(n = malloc (sizeof(*n))))
459 logf (LOG_FATAL|LOG_ERRNO, "malloc");
462 n->sysno = rec->sysno;
463 for (i = 0; i < REC_NO_INFO; i++)
464 n->info[i] = rec_strdup (rec->info[i]);