+struct trunc_info {
+ int *indx;
+ char **heap;
+ int heapnum;
+ int (*cmp)(const void *p1, const void *p2);
+ int keysize;
+ char *swapbuf;
+ char *tmpbuf;
+ char *buf;
+};
+
+static void heap_swap (struct trunc_info *ti, int i1, int i2)
+{
+ int swap;
+
+ memcpy (ti->swapbuf, ti->heap[i1], ti->keysize);
+ memcpy (ti->heap[i1], ti->heap[i2], ti->keysize);
+ memcpy (ti->heap[i2], ti->swapbuf, ti->keysize);
+
+ swap = ti->indx[i1];
+ ti->indx[i1] = ti->indx[i2];
+ ti->indx[i2] = swap;
+}
+
+static void heap_delete (struct trunc_info *ti)
+{
+ int cur = 1, child = 2;
+
+ assert (ti->heapnum > 0);
+ memcpy (ti->heap[1], ti->heap[ti->heapnum], ti->keysize);
+ ti->indx[1] = ti->indx[ti->heapnum--];
+ while (child <= ti->heapnum) {
+ if (child < ti->heapnum &&
+ (*ti->cmp)(ti->heap[child], ti->heap[1+child]) > 0)
+ child++;
+ if ((*ti->cmp)(ti->heap[cur], ti->heap[child]) > 0)
+ {
+ heap_swap (ti, cur, child);
+ cur = child;
+ child = 2*cur;
+ }
+ else
+ break;
+ }
+}
+
+static void heap_insert (struct trunc_info *ti, const char *buf, int indx)
+{
+ int cur, parent;
+
+ cur = ++(ti->heapnum);
+ memcpy (ti->heap[cur], buf, ti->keysize);
+ ti->indx[cur] = indx;
+ parent = cur/2;
+ while (parent && (*ti->cmp)(ti->heap[parent], ti->heap[cur]) > 0)
+ {
+ heap_swap (ti, cur, parent);
+ cur = parent;
+ parent = cur/2;
+ }
+}
+
+static
+struct trunc_info *heap_init (int size, int key_size,
+ int (*cmp)(const void *p1, const void *p2))
+{
+ struct trunc_info *ti = xmalloc (sizeof(*ti));
+ int i;
+
+ ++size;
+ ti->heapnum = 0;
+ ti->keysize = key_size;
+ ti->cmp = cmp;
+ ti->indx = xmalloc (size * sizeof(*ti->indx));
+ ti->heap = xmalloc (size * sizeof(*ti->heap));
+ ti->swapbuf = xmalloc (ti->keysize);
+ ti->tmpbuf = xmalloc (ti->keysize);
+ ti->buf = xmalloc (size * ti->keysize);
+ for (i = size; --i >= 0; )
+ ti->heap[i] = ti->buf + ti->keysize * i;
+ return ti;
+}
+
+static void heap_close (struct trunc_info *ti)
+{
+ xfree (ti->indx);
+ xfree (ti->heap);
+ xfree (ti->swapbuf);
+ xfree (ti->tmpbuf);
+ xfree (ti);
+}
+
+static RSET rset_trunc (ISAM isam, ISAM_P *isam_p, int from, int to,
+ int merge_chunk)
+{
+ logf (LOG_DEBUG, "rset_trunc, range=%d-%d", from, to-1);
+ if (to - from > merge_chunk)
+ {
+ return NULL;
+ }
+ else
+ {
+ ISPT *ispt;
+ int i;
+ struct trunc_info *ti;
+ RSET result;
+ RSFD rsfd;
+ rset_temp_parms parms;
+
+ ispt = xmalloc (sizeof(*ispt) * (to-from));
+ parms.key_size = sizeof (struct it_key);
+ result = rset_create (rset_kind_temp, &parms);
+ rsfd = rset_open (result, 1);
+
+ ti = heap_init (to-from, sizeof(struct it_key),
+ key_compare);
+ for (i = to-from; --i >= 0; )
+ {
+ ispt[i] = is_position (isam, isam_p[from+i]);
+ if (is_readkey (ispt[i], ti->tmpbuf))
+ heap_insert (ti, ti->tmpbuf, i);
+ }
+ while (ti->heapnum)
+ {
+ int n = ti->indx[1];
+
+ rset_write (result, rsfd, ti->heap[1]);
+ heap_delete (ti);
+ if (is_readkey (ispt[n], ti->tmpbuf))
+ heap_insert (ti, ti->tmpbuf, n);
+ }
+ for (i = to-from; --i >= 0; )
+ is_pt_free (ispt[i]);
+ rset_close (result, rsfd);
+ heap_close (ti);
+ xfree (ispt);
+ return result;
+ }
+}
+