2 * Copyright (C) 1994-1995, Index Data I/S
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.4 1995-11-20 16:59:46 adam
8 * New update method: the 'old' keys are saved for each records.
10 * Revision 1.3 1995/11/16 15:34:55 adam
11 * Uses new record management system in both indexer and server.
13 * Revision 1.2 1995/11/15 19:13:08 adam
14 * Work on record management.
16 * Revision 1.1 1995/11/15 14:46:20 adam
17 * Started work on better record management system.
50 struct record_cache_entry *record_cache;
53 struct record_cache_entry {
58 struct record_index_entry {
70 #define REC_HEAD_MAGIC "rechead"
72 char *rec_strdup (const char *s, size_t *len)
85 logf (LOG_FATAL|LOG_ERRNO, "malloc");
92 static void rec_write_head (Records p)
97 assert (p->index_fd != -1);
98 if (lseek (p->index_fd, (off_t) 0, SEEK_SET) == -1)
100 logf (LOG_FATAL|LOG_ERRNO, "lseek to 0 in %s", p->index_fname);
103 r = write (p->index_fd, &p->head, sizeof(p->head));
107 logf (LOG_FATAL|LOG_ERRNO, "write head of %s", p->index_fname);
109 case sizeof(p->head):
112 logf (LOG_FATAL, "write head of %s. wrote %d", p->index_fname, r);
117 Records rec_open (int rw)
122 if (!(p = malloc (sizeof(*p))))
124 logf (LOG_FATAL|LOG_ERRNO, "malloc");
130 p->data_fname = "recdata";
132 p->index_fname = "recindex";
133 p->index_fd = open (p->index_fname,
134 rw ? (O_RDWR|O_CREAT) : O_RDONLY, 0666);
135 if (p->index_fd == -1)
137 logf (LOG_FATAL|LOG_ERRNO, "open %s", p->index_fname);
140 r = read (p->index_fd, &p->head, sizeof(p->head));
144 logf (LOG_FATAL|LOG_ERRNO, "read %s", p->index_fname);
147 memcpy (p->head.magic, REC_HEAD_MAGIC, sizeof(p->head.magic));
148 p->head.index_free = 0;
149 p->head.index_last = 1;
150 p->head.no_records = 0;
151 p->head.data_size = 0;
152 p->head.data_slack = 0;
153 p->head.data_used = 0;
157 case sizeof(p->head):
158 if (memcmp (p->head.magic, REC_HEAD_MAGIC, sizeof(p->head.magic)))
160 logf (LOG_FATAL, "read %s. bad header", p->index_fname);
165 logf (LOG_FATAL, "read head of %s. expected %d. got %d",
166 p->index_fname, sizeof(p->head), r);
169 p->data_fd = open (p->data_fname,
170 rw ? (O_RDWR|O_CREAT) : O_RDONLY, 0666);
171 if (p->data_fd == -1)
173 logf (LOG_FATAL|LOG_ERRNO, "open %s", p->data_fname);
178 if (!(p->record_cache = malloc (sizeof(*p->record_cache)*p->cache_max)))
180 logf (LOG_FATAL|LOG_ERRNO, "malloc");
186 static void read_indx (Records p, int sysno, void *buf, int itemsize)
189 off_t pos = (sysno-1)*itemsize + sizeof(p->head);
191 if (lseek (p->index_fd, pos, SEEK_SET) == (pos) -1)
193 logf (LOG_FATAL|LOG_ERRNO, "seek in %s to pos %ld",
194 p->index_fname, (long) pos);
197 r = read (p->index_fd, buf, itemsize);
201 logf (LOG_FATAL|LOG_ERRNO, "read in %s at pos %ld",
202 p->index_fname, (long) pos);
204 logf (LOG_FATAL, "read in %s at pos %ld",
205 p->index_fname, (long) pos);
210 static void rec_write_single (Records p, Record rec)
212 struct record_index_entry entry;
213 int r, i, size = 0, got;
215 off_t pos = (rec->sysno-1)*sizeof(entry) + sizeof(p->head);
217 for (i = 0; i < REC_NO_INFO; i++)
219 size += sizeof(*rec->size);
221 size += sizeof(*rec->size) + rec->size[i];
223 entry.u.used.offset = p->head.data_size;
224 entry.u.used.size = size;
225 p->head.data_size += size;
226 p->head.data_used += size;
228 if (lseek (p->index_fd, pos, SEEK_SET) == (pos) -1)
230 logf (LOG_FATAL|LOG_ERRNO, "seek in %s to pos %ld",
231 p->index_fname, (long) pos);
234 r = write (p->index_fd, &entry, sizeof(entry));
235 if (r != sizeof(entry))
238 logf (LOG_FATAL|LOG_ERRNO, "write of %s at pos %ld",
239 p->index_fname, (long) pos);
241 logf (LOG_FATAL, "write of %s at pos %ld",
242 p->index_fname, (long) pos);
245 if (lseek (p->data_fd, entry.u.used.offset, SEEK_SET) == -1)
247 logf (LOG_FATAL|LOG_ERRNO, "lseek in %s to pos %ld",
248 p->data_fname, entry.u.used.offset);
251 if (p->tmp_size < entry.u.used.size)
254 p->tmp_size = entry.u.used.size + 16384;
255 if (!(p->tmp_buf = malloc (p->tmp_size)))
257 logf (LOG_FATAL|LOG_ERRNO, "malloc");
262 for (i = 0; i < REC_NO_INFO; i++)
264 memcpy (cptr, &rec->size[i], sizeof(*rec->size));
265 cptr += sizeof(*rec->size);
268 memcpy (cptr, rec->info[i], rec->size[i]);
269 cptr += rec->size[i];
272 for (got = 0; got < entry.u.used.size; got += r)
274 r = write (p->data_fd, p->tmp_buf + got, entry.u.used.size - got);
277 logf (LOG_FATAL|LOG_ERRNO, "write of %s", p->data_fname);
283 static void rec_cache_flush (Records p)
286 for (i = 0; i<p->cache_cur; i++)
288 struct record_cache_entry *e = p->record_cache + i;
290 rec_write_single (p, e->rec);
296 static Record *rec_cache_lookup (Records p, int sysno, int dirty)
299 for (i = 0; i<p->cache_cur; i++)
301 struct record_cache_entry *e = p->record_cache + i;
302 if (e->rec->sysno == sysno)
312 static void rec_cache_insert (Records p, Record rec, int dirty)
314 struct record_cache_entry *e;
316 if (p->cache_cur == p->cache_max)
318 assert (p->cache_cur < p->cache_max);
320 e = p->record_cache + (p->cache_cur)++;
322 e->rec = rec_cp (rec);
325 void rec_close (Records *p)
329 rec_cache_flush (*p);
330 free ((*p)->record_cache);
335 if ((*p)->index_fd != -1)
336 close ((*p)->index_fd);
338 if ((*p)->data_fd != -1)
339 close ((*p)->data_fd);
341 free ((*p)->tmp_buf);
347 Record rec_get (Records p, int sysno)
351 struct record_index_entry entry;
358 if ((recp = rec_cache_lookup (p, sysno, 0)))
359 return rec_cp (*recp);
361 read_indx (p, sysno, &entry, sizeof(entry));
363 if (!(rec = malloc (sizeof(*rec))))
365 logf (LOG_FATAL|LOG_ERRNO, "malloc");
368 if (lseek (p->data_fd, entry.u.used.offset, SEEK_SET) == -1)
370 logf (LOG_FATAL|LOG_ERRNO, "lseek in %s to pos %ld",
371 p->data_fname, entry.u.used.offset);
374 if (p->tmp_size < entry.u.used.size)
377 p->tmp_size = entry.u.used.size + 16384;
378 if (!(p->tmp_buf = malloc (p->tmp_size)))
380 logf (LOG_FATAL|LOG_ERRNO, "malloc");
384 for (got = 0; got < entry.u.used.size; got += r)
386 r = read (p->data_fd, p->tmp_buf + got, entry.u.used.size - got);
389 logf (LOG_FATAL|LOG_ERRNO, "read of %s", p->data_fname);
396 for (i = 0; i < REC_NO_INFO; i++)
398 memcpy (&rec->size[i], nptr, sizeof(*rec->size));
399 nptr += sizeof(*rec->size);
402 rec->info[i] = malloc (rec->size[i]);
403 memcpy (rec->info[i], nptr, rec->size[i]);
404 nptr += rec->size[i];
409 rec_cache_insert (p, rec, 0);
413 Record rec_new (Records p)
419 if (!(rec = malloc (sizeof(*rec))))
421 logf (LOG_FATAL|LOG_ERRNO, "malloc");
424 if (p->head.index_free == 0)
425 sysno = (p->head.index_last)++;
428 struct record_index_entry entry;
430 read_indx (p, p->head.index_free, &entry, sizeof(entry));
431 sysno = p->head.index_free;
432 p->head.index_free = entry.u.free.next;
434 (p->head.no_records)++;
436 for (i = 0; i < REC_NO_INFO; i++)
441 rec_cache_insert (p, rec, 1);
445 void rec_put (Records p, Record *recpp)
449 if ((recp = rec_cache_lookup (p, (*recpp)->sysno, 1)))
456 rec_cache_insert (p, *recpp, 1);
462 void rec_rm (Record *recpp)
465 for (i = 0; i < REC_NO_INFO; i++)
466 free ((*recpp)->info[i]);
471 Record rec_cp (Record rec)
476 if (!(n = malloc (sizeof(*n))))
478 logf (LOG_FATAL|LOG_ERRNO, "malloc");
481 n->sysno = rec->sysno;
482 for (i = 0; i < REC_NO_INFO; i++)
490 n->size[i] = rec->size[i];
491 if (!(n->info[i] = malloc (rec->size[i])))
493 logf (LOG_FATAL|LOG_ERRNO, "malloc. rec_cp");
496 memcpy (n->info[i], rec->info[i], rec->size[i]);