X-Git-Url: http://git.indexdata.com/?p=idzebra-moved-to-github.git;a=blobdiff_plain;f=index%2Frecindex.c;h=b8ccae7d80494a4708a0f5521fb0411cec49c953;hp=f64816cda7585c55cdecbfb658d122cff0bca760;hb=f3e73ab63fbc960d863d9c14bab3b9e79c400ffa;hpb=5214040d316f7b5228e46e1749505e3c0c8869d4 diff --git a/index/recindex.c b/index/recindex.c index f64816c..b8ccae7 100644 --- a/index/recindex.c +++ b/index/recindex.c @@ -4,7 +4,10 @@ * Sebastian Hammer, Adam Dickmeiss * * $Log: recindex.c,v $ - * Revision 1.1 1995-11-15 14:46:20 adam + * Revision 1.2 1995-11-15 19:13:08 adam + * Work on record management. + * + * Revision 1.1 1995/11/15 14:46:20 adam * Started work on better record management system. * */ @@ -18,29 +21,85 @@ #include "recindex.h" +struct records_info { + int rw; + int index_fd; + char *index_fname; + int data_fd; + char *data_fname; + struct records_head { + char magic[8]; + int no_records; + int index_free; + int index_last; + int data_size; + int data_slack; + int data_used; + } head; + char *tmp_buf; + int tmp_size; + int cache_size; + int cache_cur; + int cache_max; + struct record_cache_entry *record_cache; +}; + +struct record_cache_entry { + Record rec; + int dirty; +}; + +struct record_index_entry { + union { + struct { + int offset; + int size; + } used; + struct { + int next; + } free; + } u; +}; + #define REC_HEAD_MAGIC "rechead" +char *rec_strdup (const char *s) +{ + char *p; + + if (!s) + return NULL; + p = malloc (strlen(s)+1); + if (!p) + { + logf (LOG_FATAL|LOG_ERRNO, "malloc"); + exit (1); + } + strcpy (p, s); + return p; +} + static void rec_write_head (Records p) { int r; assert (p); - assert (p->fd != -1); - if (lseek (p->fd, (off_t) 0, SEEK_SET) == -1) + assert (p->index_fd != -1); + if (lseek (p->index_fd, (off_t) 0, SEEK_SET) == -1) { - logf (LOG_FATAL|LOG_ERRNO, "lseek to 0 in %s", p->fname); + logf (LOG_FATAL|LOG_ERRNO, "lseek to 0 in %s", p->index_fname); exit (1); } - r = write (p->fd, &p->head, sizeof(p->head)); + r = write (p->index_fd, &p->head, sizeof(p->head)); switch (r) { case -1: - logf (LOG_FATAL|LOG_ERRNO, "write head of %s", p->fname); + logf (LOG_FATAL|LOG_ERRNO, "write head of %s", p->index_fname); exit (1); case sizeof(p->head): break; default: - logf (LOG_FATAL, "write head of %s. wrote %d", p->fname, r); + logf (LOG_FATAL, "write head of %s. wrote %d", p->index_fname, r); exit (1); } } @@ -55,60 +114,348 @@ Records rec_open (int rw) logf (LOG_FATAL|LOG_ERRNO, "malloc"); exit (1); } - p->fname = "recindex"; - p->fd = open (p->fname, rw ? (O_RDWR|O_CREAT) : O_RDONLY, 0666); - if (p->fd == -1) + p->rw = rw; + p->tmp_buf = NULL; + p->tmp_size = 0; + p->data_fname = "recdata"; + p->data_fd = -1; + p->index_fname = "recindex"; + p->index_fd = open (p->index_fname, + rw ? (O_RDWR|O_CREAT) : O_RDONLY, 0666); + if (p->index_fd == -1) { - logf (LOG_FATAL|LOG_ERRNO, "open %s", p->fname); + logf (LOG_FATAL|LOG_ERRNO, "open %s", p->index_fname); exit (1); } - r = read (p->fd, &p->head, sizeof(p->head)); + r = read (p->index_fd, &p->head, sizeof(p->head)); switch (r) { case -1: - logf (LOG_FATAL|LOG_ERRNO, "read %s", p->fname); + logf (LOG_FATAL|LOG_ERRNO, "read %s", p->index_fname); exit (1); case 0: + p->head.index_free = 0; + p->head.index_last = 1; p->head.no_records = 0; - p->head.freelist = 0; + p->head.data_size = 0; + p->head.data_slack = 0; + p->head.data_used = 0; if (rw) rec_write_head (p); break; case sizeof(p->head): if (memcmp (p->head.magic, REC_HEAD_MAGIC, sizeof(p->head.magic))) { - logf (LOG_FATAL, "read %s. bad header", p->fname); + logf (LOG_FATAL, "read %s. bad header", p->index_fname); exit (1); } break; default: logf (LOG_FATAL, "read head of %s. expected %d. got %d", - p->fname, sizeof(p->head), r); + p->index_fname, sizeof(p->head), r); + exit (1); + } + p->data_fd = open (p->data_fname, + rw ? (O_RDWR|O_CREAT) : O_RDONLY, 0666); + if (p->data_fd == -1) + { + logf (LOG_FATAL|LOG_ERRNO, "open %s", p->data_fname); + exit (1); + } + p->cache_max = 100; + p->cache_cur = 0; + if (!(p->record_cache = malloc (sizeof(*p->record_cache)*p->cache_max))) + { + logf (LOG_FATAL|LOG_ERRNO, "malloc"); exit (1); } return p; } -void rec_close (Records p) +static void read_indx (Records p, int sysno, void *buf, int itemsize) +{ + int r; + off_t pos = (sysno-1)*itemsize + sizeof(p->head); + + if (lseek (p->index_fd, pos, SEEK_SET) == (pos) -1) + { + logf (LOG_FATAL|LOG_ERRNO, "seek in %s to pos %ld", + p->index_fname, (long) pos); + exit (1); + } + r = read (p->index_fd, buf, itemsize); + if (r != itemsize) + { + if (r == -1) + logf (LOG_FATAL|LOG_ERRNO, "read in %s at pos %ld", + p->index_fname, (long) pos); + else + logf (LOG_FATAL, "read in %s at pos %ld", + p->index_fname, (long) pos); + exit (1); + } +} + +static void rec_write_single (Records p, Record rec) +{ + struct record_index_entry entry; + int r, i, size = 0, got; + char *cptr; + off_t pos = (rec->sysno-1)*sizeof(entry) + sizeof(p->head); + + for (i = 0; i < REC_NO_INFO; i++) + if (!rec->info[i]) + size++; + else + size += strlen(rec->info[i])+1; + + entry.u.used.offset = p->head.data_size; + entry.u.used.size = size; + p->head.data_size += size; + p->head.data_used += size; + + if (lseek (p->index_fd, pos, SEEK_SET) == (pos) -1) + { + logf (LOG_FATAL|LOG_ERRNO, "seek in %s to pos %ld", + p->index_fname, (long) pos); + exit (1); + } + r = write (p->index_fd, &entry, sizeof(entry)); + if (r != sizeof(entry)) + { + if (r == -1) + logf (LOG_FATAL|LOG_ERRNO, "write of %s at pos %ld", + p->index_fname, (long) pos); + else + logf (LOG_FATAL, "write of %s at pos %ld", + p->index_fname, (long) pos); + exit (1); + } + if (lseek (p->data_fd, entry.u.used.offset, SEEK_SET) == -1) + { + logf (LOG_FATAL|LOG_ERRNO, "lseek in %s to pos %ld", + p->data_fname, entry.u.used.offset); + exit (1); + } + if (p->tmp_size < entry.u.used.size) + { + free (p->tmp_buf); + p->tmp_size = entry.u.used.size + 16384; + if (!(p->tmp_buf = malloc (p->tmp_size))) + { + logf (LOG_FATAL|LOG_ERRNO, "malloc"); + exit (1); + } + } + cptr = p->tmp_buf; + for (i = 0; i < REC_NO_INFO; i++) + if (!rec->info[i]) + *cptr++ = '\0'; + else + { + strcpy (cptr, rec->info[i]); + cptr += strlen(rec->info[i]) + 1; + } + for (got = 0; got < entry.u.used.size; got += r) + { + r = write (p->data_fd, p->tmp_buf + got, entry.u.used.size - got); + if (r <= 0) + { + logf (LOG_FATAL|LOG_ERRNO, "write of %s", p->data_fname); + exit (1); + } + got += r; + } +} + +static void rec_cache_flush (Records p) +{ + int i; + for (i = 0; icache_cur; i++) + { + struct record_cache_entry *e = p->record_cache + i; + if (e->dirty) + rec_write_single (p, e->rec); + rec_rm (e->rec); + } + p->cache_cur = 0; +} + +static Record *rec_cache_lookup (Records p, int sysno, int dirty) +{ + int i; + for (i = 0; icache_cur; i++) + { + struct record_cache_entry *e = p->record_cache + i; + if (e->rec->sysno == sysno) + { + if (dirty) + e->dirty = 1; + return &e->rec; + } + } + return NULL; +} + +static void rec_cache_insert (Records p, Record rec, int dirty) { - if (p->fd != -1) - close (p->fd); - free (p); + struct record_cache_entry *e; + + if (p->cache_cur == p->cache_max) + rec_cache_flush (p); + assert (p->cache_cur < p->cache_max); + + e = p->record_cache + (p->cache_cur)++; + e->dirty = 1; + e->rec = rec_cp (rec); +} + +void rec_close (Records *p) +{ + assert (*p); + + rec_cache_flush (*p); + free ((*p)->record_cache); + + if ((*p)->index_fd != -1) + close ((*p)->index_fd); + + if ((*p)->data_fd != -1) + close ((*p)->data_fd); + + free ((*p)->tmp_buf); + + free (*p); + *p = NULL; } Record rec_get (Records p, int sysno) { + int i; + Record rec, *recp; + struct record_index_entry entry; + int r, got; + char *nptr; + + assert (sysno > 0); assert (p); - return NULL; + + if ((recp = rec_cache_lookup (p, sysno, 0))) + return rec_cp (*recp); + + read_indx (p, sysno, &entry, sizeof(entry)); + + if (!(rec = malloc (sizeof(*rec)))) + { + logf (LOG_FATAL|LOG_ERRNO, "malloc"); + exit (1); + } + if (lseek (p->data_fd, entry.u.used.offset, SEEK_SET) == -1) + { + logf (LOG_FATAL|LOG_ERRNO, "lseek in %s to pos %ld", + p->data_fname, entry.u.used.offset); + exit (1); + } + if (p->tmp_size < entry.u.used.size) + { + free (p->tmp_buf); + p->tmp_size = entry.u.used.size + 16384; + if (!(p->tmp_buf = malloc (p->tmp_size))) + { + logf (LOG_FATAL|LOG_ERRNO, "malloc"); + exit (1); + } + } + for (got = 0; got < entry.u.used.size; got += r) + { + r = read (p->data_fd, p->tmp_buf + got, entry.u.used.size - got); + if (r <= 0) + { + logf (LOG_FATAL|LOG_ERRNO, "read of %s", p->data_fname); + exit (1); + } + got += r; + } + rec->sysno = sysno; + + nptr = p->tmp_buf; + for (i = 0; i < REC_NO_INFO; i++) + if (*nptr) + { + rec->info[i] = rec_strdup (nptr); + nptr += strlen(nptr)+1; + } + else + { + nptr++; + rec->info[i] = NULL; + } + rec_cache_insert (p, rec, 0); + return rec; } Record rec_new (Records p) { + int sysno, i; + Record rec; + assert (p); - return NULL; + if (!(rec = malloc (sizeof(*rec)))) + { + logf (LOG_FATAL|LOG_ERRNO, "malloc"); + exit (1); + } + if (p->head.index_free == 0) + sysno = (p->head.index_last)++; + else + { + struct record_index_entry entry; + + read_indx (p, p->head.index_free, &entry, sizeof(entry)); + sysno = p->head.index_free; + p->head.index_free = entry.u.free.next; + } + (p->head.no_records)++; + rec->sysno = sysno; + for (i = 0; i < REC_NO_INFO; i++) + rec->info[i] = NULL; + rec_cache_insert (p, rec, 1); + return rec; } void rec_put (Records p, Record rec) { - assert (p); + Record *recp; + + if ((recp = rec_cache_lookup (p, rec->sysno, 1))) + { + rec_rm (*recp); + *recp = rec_cp (rec); + } + else + rec_cache_insert (p, rec, 1); +} + +void rec_rm (Record rec) +{ + int i; + for (i = 0; i < REC_NO_INFO; i++) + free (rec->info[i]); + free (rec); +} + +Record rec_cp (Record rec) +{ + Record n; + int i; + + if (!(n = malloc (sizeof(*n)))) + { + logf (LOG_FATAL|LOG_ERRNO, "malloc"); + exit (1); + } + n->sysno = rec->sysno; + for (i = 0; i < REC_NO_INFO; i++) + n->info[i] = rec_strdup (rec->info[i]); + return n; }