- if (p->tmp_size < size + 256 ||
- p->tmp_size < p->head.block_size[dst_type]*2)
- {
- xfree (p->tmp_buf);
- p->tmp_size = size + p->head.block_size[dst_type]*2 + 256;
- p->tmp_buf = xmalloc (p->tmp_size);
- }
-}
-
-static int read_indx (Records p, int sysno, void *buf, int itemsize,
- int ignoreError)
-{
- int r;
- int pos = (sysno-1)*itemsize;
-
- r = bf_read (p->index_BFile, 1+pos/128, pos%128, itemsize, buf);
- if (r != 1 && !ignoreError)
- {
- logf (LOG_FATAL|LOG_ERRNO, "read in %s at pos %ld",
- p->index_fname, (long) pos);
- abort ();
- exit (1);
- }
- return r;
-}
-
-static void write_indx (Records p, int sysno, void *buf, int itemsize)
-{
- int pos = (sysno-1)*itemsize;
-
- bf_write (p->index_BFile, 1+pos/128, pos%128, itemsize, buf);
-}
-
-static void rec_release_blocks (Records p, int sysno)
-{
- struct record_index_entry entry;
- int freeblock, freenext;
- int dst_type;
-
- if (read_indx (p, sysno, &entry, sizeof(entry), 1) != 1)
- return ;
- freeblock = entry.u.used.next;
- assert (freeblock > 0);
- dst_type = freeblock & 7;
- assert (dst_type < REC_BLOCK_TYPES);
- freeblock = freeblock / 8;
- while (freeblock)
- {
- if (bf_read (p->data_BFile[dst_type], freeblock, 0, sizeof(freenext),
- &freenext) != 1)
- {
- logf (LOG_FATAL|LOG_ERRNO, "read in rec_del_single");
- exit (1);
- }
- if (bf_write (p->data_BFile[dst_type], freeblock, 0, sizeof(freenext),
- &p->head.block_free[dst_type]))
- {
- logf (LOG_FATAL|LOG_ERRNO, "write in rec_del_single");
- exit (1);
- }
- p->head.block_free[dst_type] = freeblock;
- freeblock = freenext;
- p->head.block_used[dst_type]--;
- }
-}
-
-static void rec_delete_single (Records p, Record rec)
-{
- struct record_index_entry entry;
-
- rec_release_blocks (p, rec->sysno);
-
- entry.u.free.next = p->head.index_free;
- p->head.index_free = rec->sysno;
- write_indx (p, rec->sysno, &entry, sizeof(entry));
-}
-
-
-static void rec_write_single (Records p, Record rec)
-{
- int i, size = 0;
- char *cptr;
- int dst_type = 0;
- int no_written = 0;
- int block_prev = -1, block_free;
- struct record_index_entry entry;
-
- for (i = 0; i < REC_NO_INFO; i++)
- if (!rec->info[i])
- size += sizeof(*rec->size);
- else
- size += sizeof(*rec->size) + rec->size[i];
-
- for (i = 1; i<REC_BLOCK_TYPES; i++)
- if (size >= p->head.block_move[i])
- dst_type = i;
-
- rec_tmp_expand (p, size, dst_type);
-
- cptr = p->tmp_buf + sizeof(int); /* a hack! */
- for (i = 0; i < REC_NO_INFO; i++)
- {
- memcpy (cptr, &rec->size[i], sizeof(*rec->size));
- cptr += sizeof(*rec->size);
- if (rec->info[i])
- {
- memcpy (cptr, rec->info[i], rec->size[i]);
- cptr += rec->size[i];
- }
- }
- cptr = p->tmp_buf;
- while (no_written < size)
- {
- block_free = p->head.block_free[dst_type];
- if (block_free)
- {
- if (bf_read (p->data_BFile[dst_type],
- block_free, 0, sizeof(*p->head.block_free),
- &p->head.block_free[dst_type]) != 1)
- {
- logf (LOG_FATAL|LOG_ERRNO, "read in %s at free block %d",
- p->data_fname[dst_type], block_free);
- }
- }
- else
- block_free = p->head.block_last[dst_type]++;
- if (block_prev == -1)
- {
- entry.u.used.next = block_free*8 + dst_type;
- entry.u.used.size = size;
-
- write_indx (p, rec->sysno, &entry, sizeof(entry));
- }
- else
- {
- memcpy (cptr, &block_free, sizeof(int));
- bf_write (p->data_BFile[dst_type], block_prev, 0, 0, cptr);
- cptr = p->tmp_buf + no_written;
- }
- block_prev = block_free;
- no_written += p->head.block_size[dst_type] - sizeof(int);
- p->head.block_used[dst_type]++;
- }
- assert (block_prev != -1);
- block_free = 0;
- memcpy (cptr, &block_free, sizeof(int));
- bf_write (p->data_BFile[dst_type], block_prev, 0,
- sizeof(int) + (p->tmp_buf+size) - cptr, cptr);
-}
-
-static void rec_update_single (Records p, Record rec)
-{
- rec_release_blocks (p, rec->sysno);
- rec_write_single (p, rec);
-}
-
-Records rec_open (int rw)
-{
- Records p;
- int i, r;
-
- p = xmalloc (sizeof(*p));
- p->rw = rw;
- p->tmp_size = 1024;
- p->tmp_buf = xmalloc (p->tmp_size);
- p->index_fname = "recindex";
- p->index_BFile = bf_open (p->index_fname, 128, rw);