2 * Copyright (C) 1994-1995, Index Data I/S
4 * Sebastian Hammer, Adam Dickmeiss
7 * Revision 1.2 1995-11-15 19:13:08 adam
8 * Work on record management.
10 * Revision 1.1 1995/11/15 14:46:20 adam
11 * Started work on better record management system.
44 struct record_cache_entry *record_cache;
47 struct record_cache_entry {
52 struct record_index_entry {
64 #define REC_HEAD_MAGIC "rechead"
66 char *rec_strdup (const char *s)
72 p = malloc (strlen(s)+1);
75 logf (LOG_FATAL|LOG_ERRNO, "malloc");
82 static void rec_write_head (Records p)
87 assert (p->index_fd != -1);
88 if (lseek (p->index_fd, (off_t) 0, SEEK_SET) == -1)
90 logf (LOG_FATAL|LOG_ERRNO, "lseek to 0 in %s", p->index_fname);
93 r = write (p->index_fd, &p->head, sizeof(p->head));
97 logf (LOG_FATAL|LOG_ERRNO, "write head of %s", p->index_fname);
102 logf (LOG_FATAL, "write head of %s. wrote %d", p->index_fname, r);
107 Records rec_open (int rw)
112 if (!(p = malloc (sizeof(*p))))
114 logf (LOG_FATAL|LOG_ERRNO, "malloc");
120 p->data_fname = "recdata";
122 p->index_fname = "recindex";
123 p->index_fd = open (p->index_fname,
124 rw ? (O_RDWR|O_CREAT) : O_RDONLY, 0666);
125 if (p->index_fd == -1)
127 logf (LOG_FATAL|LOG_ERRNO, "open %s", p->index_fname);
130 r = read (p->index_fd, &p->head, sizeof(p->head));
134 logf (LOG_FATAL|LOG_ERRNO, "read %s", p->index_fname);
137 p->head.index_free = 0;
138 p->head.index_last = 1;
139 p->head.no_records = 0;
140 p->head.data_size = 0;
141 p->head.data_slack = 0;
142 p->head.data_used = 0;
146 case sizeof(p->head):
147 if (memcmp (p->head.magic, REC_HEAD_MAGIC, sizeof(p->head.magic)))
149 logf (LOG_FATAL, "read %s. bad header", p->index_fname);
154 logf (LOG_FATAL, "read head of %s. expected %d. got %d",
155 p->index_fname, sizeof(p->head), r);
158 p->data_fd = open (p->data_fname,
159 rw ? (O_RDWR|O_CREAT) : O_RDONLY, 0666);
160 if (p->data_fd == -1)
162 logf (LOG_FATAL|LOG_ERRNO, "open %s", p->data_fname);
167 if (!(p->record_cache = malloc (sizeof(*p->record_cache)*p->cache_max)))
169 logf (LOG_FATAL|LOG_ERRNO, "malloc");
175 static void read_indx (Records p, int sysno, void *buf, int itemsize)
178 off_t pos = (sysno-1)*itemsize + sizeof(p->head);
180 if (lseek (p->index_fd, pos, SEEK_SET) == (pos) -1)
182 logf (LOG_FATAL|LOG_ERRNO, "seek in %s to pos %ld",
183 p->index_fname, (long) pos);
186 r = read (p->index_fd, buf, itemsize);
190 logf (LOG_FATAL|LOG_ERRNO, "read in %s at pos %ld",
191 p->index_fname, (long) pos);
193 logf (LOG_FATAL, "read in %s at pos %ld",
194 p->index_fname, (long) pos);
199 static void rec_write_single (Records p, Record rec)
201 struct record_index_entry entry;
202 int r, i, size = 0, got;
204 off_t pos = (rec->sysno-1)*sizeof(entry) + sizeof(p->head);
206 for (i = 0; i < REC_NO_INFO; i++)
210 size += strlen(rec->info[i])+1;
212 entry.u.used.offset = p->head.data_size;
213 entry.u.used.size = size;
214 p->head.data_size += size;
215 p->head.data_used += size;
217 if (lseek (p->index_fd, pos, SEEK_SET) == (pos) -1)
219 logf (LOG_FATAL|LOG_ERRNO, "seek in %s to pos %ld",
220 p->index_fname, (long) pos);
223 r = write (p->index_fd, &entry, sizeof(entry));
224 if (r != sizeof(entry))
227 logf (LOG_FATAL|LOG_ERRNO, "write of %s at pos %ld",
228 p->index_fname, (long) pos);
230 logf (LOG_FATAL, "write of %s at pos %ld",
231 p->index_fname, (long) pos);
234 if (lseek (p->data_fd, entry.u.used.offset, SEEK_SET) == -1)
236 logf (LOG_FATAL|LOG_ERRNO, "lseek in %s to pos %ld",
237 p->data_fname, entry.u.used.offset);
240 if (p->tmp_size < entry.u.used.size)
243 p->tmp_size = entry.u.used.size + 16384;
244 if (!(p->tmp_buf = malloc (p->tmp_size)))
246 logf (LOG_FATAL|LOG_ERRNO, "malloc");
251 for (i = 0; i < REC_NO_INFO; i++)
256 strcpy (cptr, rec->info[i]);
257 cptr += strlen(rec->info[i]) + 1;
259 for (got = 0; got < entry.u.used.size; got += r)
261 r = write (p->data_fd, p->tmp_buf + got, entry.u.used.size - got);
264 logf (LOG_FATAL|LOG_ERRNO, "write of %s", p->data_fname);
271 static void rec_cache_flush (Records p)
274 for (i = 0; i<p->cache_cur; i++)
276 struct record_cache_entry *e = p->record_cache + i;
278 rec_write_single (p, e->rec);
284 static Record *rec_cache_lookup (Records p, int sysno, int dirty)
287 for (i = 0; i<p->cache_cur; i++)
289 struct record_cache_entry *e = p->record_cache + i;
290 if (e->rec->sysno == sysno)
300 static void rec_cache_insert (Records p, Record rec, int dirty)
302 struct record_cache_entry *e;
304 if (p->cache_cur == p->cache_max)
306 assert (p->cache_cur < p->cache_max);
308 e = p->record_cache + (p->cache_cur)++;
310 e->rec = rec_cp (rec);
313 void rec_close (Records *p)
317 rec_cache_flush (*p);
318 free ((*p)->record_cache);
320 if ((*p)->index_fd != -1)
321 close ((*p)->index_fd);
323 if ((*p)->data_fd != -1)
324 close ((*p)->data_fd);
326 free ((*p)->tmp_buf);
332 Record rec_get (Records p, int sysno)
336 struct record_index_entry entry;
343 if ((recp = rec_cache_lookup (p, sysno, 0)))
344 return rec_cp (*recp);
346 read_indx (p, sysno, &entry, sizeof(entry));
348 if (!(rec = malloc (sizeof(*rec))))
350 logf (LOG_FATAL|LOG_ERRNO, "malloc");
353 if (lseek (p->data_fd, entry.u.used.offset, SEEK_SET) == -1)
355 logf (LOG_FATAL|LOG_ERRNO, "lseek in %s to pos %ld",
356 p->data_fname, entry.u.used.offset);
359 if (p->tmp_size < entry.u.used.size)
362 p->tmp_size = entry.u.used.size + 16384;
363 if (!(p->tmp_buf = malloc (p->tmp_size)))
365 logf (LOG_FATAL|LOG_ERRNO, "malloc");
369 for (got = 0; got < entry.u.used.size; got += r)
371 r = read (p->data_fd, p->tmp_buf + got, entry.u.used.size - got);
374 logf (LOG_FATAL|LOG_ERRNO, "read of %s", p->data_fname);
382 for (i = 0; i < REC_NO_INFO; i++)
385 rec->info[i] = rec_strdup (nptr);
386 nptr += strlen(nptr)+1;
393 rec_cache_insert (p, rec, 0);
397 Record rec_new (Records p)
403 if (!(rec = malloc (sizeof(*rec))))
405 logf (LOG_FATAL|LOG_ERRNO, "malloc");
408 if (p->head.index_free == 0)
409 sysno = (p->head.index_last)++;
412 struct record_index_entry entry;
414 read_indx (p, p->head.index_free, &entry, sizeof(entry));
415 sysno = p->head.index_free;
416 p->head.index_free = entry.u.free.next;
418 (p->head.no_records)++;
420 for (i = 0; i < REC_NO_INFO; i++)
422 rec_cache_insert (p, rec, 1);
426 void rec_put (Records p, Record rec)
430 if ((recp = rec_cache_lookup (p, rec->sysno, 1)))
433 *recp = rec_cp (rec);
436 rec_cache_insert (p, rec, 1);
439 void rec_rm (Record rec)
442 for (i = 0; i < REC_NO_INFO; i++)
447 Record rec_cp (Record rec)
452 if (!(n = malloc (sizeof(*n))))
454 logf (LOG_FATAL|LOG_ERRNO, "malloc");
457 n->sysno = rec->sysno;
458 for (i = 0; i < REC_NO_INFO; i++)
459 n->info[i] = rec_strdup (rec->info[i]);