+/*==================== COMPACTING ====================*/
+
+struct ht_forall_ctx {
+ struct cdb_make cdbm;
+ FILE *mainfile;
+ int lexminvall;
+ long *reccount;
+ const char *lexminval;
+};
+
+/*---------- helper functions ----------*/
+
+static int expiredp(const HashValue *val, struct ht_forall_ctx *a) {
+ int r, l;
+ if (!val->len) return 0;
+ l= val->len < a->lexminvall ? val->len : a->lexminvall;
+ r= memcmp(val->data, a->lexminval, l);
+ if (r>0) return 0;
+ if (r<0) return 1;
+ return val->len < a->lexminvall;
+}
+
+static int delete_ifexpired(const char *key, HashValue *val,
+ struct ht_forall_ctx *a) {
+ if (!expiredp(val, a)) return 0;
+ val->len= 0;
+ /* we don't actually need to realloc it to free the memory because
+ * this will shortly all be deleted as part of the compaction */
+ return 0;
+}
+
+static int addto_cdb(const char *key, HashValue *val,
+ struct ht_forall_ctx *a) {
+ return cdb_make_add(&a->cdbm, key, strlen(key), val->data, val->len);
+}
+
+static int addto_main(const char *key, HashValue *val,
+ struct ht_forall_ctx *a) {
+ int r;
+
+ (*a->reccount)++;
+
+ r= fprintf(a->mainfile, "+%d,%d:%s->", strlen(key), val->len, key);
+ if (r<0) return -1;
+
+ r= fwrite(val->data, 1, val->len, a->mainfile);
+ if (r != val->len) return -1;
+
+ return 0;
+}
+
+/*---------- compact main entrypoint ----------*/