+
+static ISAM_P is_address(int type, int pos)
+{
+ ISAM_P r;
+
+ r = pos << 2;
+ r |= type;
+ return r;
+}
+
+int sort_input(const void *p1, const void *p2)
+{
+ int rs;
+
+ if ((rs = (*extcmp)(((char *)p1) + 1, ((char *)p2) + 1)))
+ return rs;
+ return *((char *)p1) - *((char*)p2);
+}
+
+ISAM_P is_merge(ISAM is, ISAM_P pos, int num, char *data)
+{
+ is_mtable tab;
+ int res;
+ char keybuf[IS_MAX_RECORD];
+ int oldnum, oldtype, i;
+ char operation, *record;
+
+ extcmp = is->cmp;
+ qsort(data, num, is_keysize(is) + 1, sort_input);
+ is_m_establish_tab(is, &tab, pos);
+ /* TODO: do something to aquire oldnum at this point */
+ if (pos)
+ if (is_m_read_full(&tab, tab.data) < 0)
+ {
+ log(LOG_FATAL, "read_full failed");
+ exit(1);
+ }
+ oldnum = tab.num_records;
+ oldtype = tab.pos_type;
+ while (num)
+ {
+ operation = *(data)++;
+ record = (char*) data;
+ data += is_keysize(is);
+ num--;
+ while (num && !memcmp(record - 1, data, is_keysize(tab.is) + 1))
+ {
+ data += 1 + is_keysize(is);
+ num--;
+ }
+ if ((res = is_m_seek_record(&tab, record)) > 0) /* no match */
+ {
+ if (operation == KEYOP_INSERT)
+ {
+ log(LOG_DEBUG, "XXInserting new record.");
+ is_m_write_record(&tab, record);
+ }
+ else
+ log(LOG_DEBUG, "XXDeletion failed to find match.");
+ }
+ else /* match found */
+ {
+ if (operation == KEYOP_INSERT)
+ {
+ log(LOG_DEBUG, "XXSkipping insertion - match found.");
+ continue;
+ }
+ else if (operation == KEYOP_DELETE)
+ {
+ /* try to avoid needlessly moving data */
+ if (num && *(data) == KEYOP_INSERT)
+ {
+ /* next key is identical insert? - NOOP - skip it */
+ if (!memcmp(record, data + 1, is_keysize(is)))
+ {
+ log(LOG_DEBUG, "XXNoop delete. skipping.");
+ data += 1 + is_keysize(is);
+ num--;
+ continue;
+ }
+ /* else check if next key can fit in this position */
+ is_m_peek_record(&tab, keybuf);
+ res = (*is->cmp)(data + 1, keybuf);
+ if (res < 0)
+ {
+ log(LOG_DEBUG, "XXReplacing record.");
+ is_m_replace_record(&tab, data + 1);
+ data += 1 + is_keysize(is);
+ num--;
+ continue;
+ }
+ }
+ log(LOG_DEBUG, "Deleting record.");
+ is_m_delete_record(&tab);
+ }
+ }
+ }
+ i = tab.pos_type;
+ while (i < tab.is->num_types - 1 && tab.num_records >
+ tab.is->types[i].max_keys)
+ i++;
+ if (i != tab.pos_type)
+ {
+ is_p_unmap(&tab);
+ tab.pos_type = i;
+ }
+ if (!oldnum || tab.pos_type != oldtype || (abs(oldnum - tab.num_records) *
+ 100) / oldnum > tab.is->repack)
+ is_p_remap(&tab);
+ else
+ is_p_align(&tab);
+ if (tab.data)
+ {
+ is_p_sync(&tab);
+ pos = is_address(tab.pos_type, tab.data->diskpos);
+ }
+ else
+ pos = 0;
+ is_m_release_tab(&tab);
+ return pos;
+}
+
+/*
+ * Locate a table of keys in an isam file. The ISPT is an individual
+ * position marker for that table.
+ */
+ISPT is_position(ISAM is, ISAM_P pos);
+
+/*
+ * Release ISPT.
+ */
+void is_pt_free(ISPT ip);