+ zint pos = (sysno-1)*itemsize;
+ int off = CAST_ZINT_TO_INT(pos%RIDX_CHUNK);
+ int sz1 = RIDX_CHUNK - off; /* sz1 is size of buffer to read.. */
+
+ if (sz1 > itemsize)
+ sz1 = itemsize; /* no more than itemsize bytes */
+
+ r = bf_read(p->index_BFile, 1+pos/RIDX_CHUNK, off, sz1, buf);
+ if (r == 1 && sz1 < itemsize) /* boundary? - must read second part */
+ r = bf_read(p->index_BFile, 2+pos/RIDX_CHUNK, 0, itemsize - sz1,
+ (char*) buf + sz1);
+ if (r != 1 && !ignoreError)
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "read in %s at pos %ld",
+ p->index_fname, (long) pos);
+ }
+ return r;
+}
+
+static void write_indx(Records p, zint sysno, void *buf, int itemsize)
+{
+ zint pos = (sysno-1)*itemsize;
+ int off = CAST_ZINT_TO_INT(pos%RIDX_CHUNK);
+ int sz1 = RIDX_CHUNK - off; /* sz1 is size of buffer to read.. */
+
+ if (sz1 > itemsize)
+ sz1 = itemsize; /* no more than itemsize bytes */
+
+ bf_write(p->index_BFile, 1+pos/RIDX_CHUNK, off, sz1, buf);
+ if (sz1 < itemsize) /* boundary? must write second part */
+ bf_write(p->index_BFile, 2+pos/RIDX_CHUNK, 0, itemsize - sz1,
+ (char*) buf + sz1);
+}
+
+static ZEBRA_RES rec_release_blocks(Records p, zint sysno)
+{
+ struct record_index_entry entry;
+ zint freeblock;
+ char block_and_ref[sizeof(zint) + sizeof(short)];
+ int dst_type;
+ int first = 1;
+
+ if (read_indx(p, sysno, &entry, sizeof(entry), 1) != 1)
+ return ZEBRA_FAIL;
+
+ freeblock = entry.next;
+ assert(freeblock > 0);
+ dst_type = CAST_ZINT_TO_INT(freeblock & 7);
+ assert(dst_type < REC_BLOCK_TYPES);
+ freeblock = freeblock / 8;
+ while (freeblock)
+ {
+ if (bf_read(p->data_BFile[dst_type], freeblock, 0,
+ first ? sizeof(block_and_ref) : sizeof(zint),
+ block_and_ref) != 1)
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "read in rec_del_single");
+ return ZEBRA_FAIL;
+ }
+ if (first)
+ {
+ short ref;
+ memcpy(&ref, block_and_ref + sizeof(freeblock), sizeof(ref));
+ --ref;
+ memcpy(block_and_ref + sizeof(freeblock), &ref, sizeof(ref));
+ if (ref)
+ {
+ if (bf_write(p->data_BFile[dst_type], freeblock, 0,
+ sizeof(block_and_ref), block_and_ref))
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "write in rec_del_single");
+ return ZEBRA_FAIL;
+ }
+ return ZEBRA_OK;
+ }
+ first = 0;
+ }
+
+ if (bf_write(p->data_BFile[dst_type], freeblock, 0, sizeof(freeblock),
+ &p->head.block_free[dst_type]))
+ {
+ yaz_log(YLOG_FATAL|YLOG_ERRNO, "write in rec_del_single");
+ return ZEBRA_FAIL;
+ }
+ p->head.block_free[dst_type] = freeblock;
+ memcpy(&freeblock, block_and_ref, sizeof(freeblock));
+
+ p->head.block_used[dst_type]--;
+ }
+ p->head.total_bytes -= entry.size;
+ return ZEBRA_OK;
+}
+
+static ZEBRA_RES rec_delete_single(Records p, Record rec)
+{
+ struct record_index_entry entry;
+
+ /* all data in entry must be reset, since it's written verbatim */
+ memset(&entry, '\0', sizeof(entry));
+ if (rec_release_blocks(p, rec_sysno_to_int(rec->sysno)) != ZEBRA_OK)
+ return ZEBRA_FAIL;