}
enum {
- IAM_LFIX_ROOT_MAGIC = 0xbedabb1edULL
+ IAM_LFIX_ROOT_MAGIC = 0xbedabb1edULL,
+ IAM_LVAR_ROOT_MAGIC = 0xb01dface
};
struct iam_lfix_root {
};
enum {
- IAM_LEAF_HEADER_MAGIC = 0x1976
+ IAM_LEAF_HEADER_MAGIC = 0x1976,
+ IAM_LVAR_LEAF_MAGIC = 0x1973
};
struct iam_leaf_head {
u_int16_t count;
};
+typedef __u32 lvar_hash_t;
+
+struct lvar_leaf_header {
+ u_int16_t vlh_magic; /* magic number IAM_LVAR_LEAF_MAGIC */
+ u_int16_t vlh_used; /* used bytes, including header */
+};
+
+struct lvar_root {
+ u_int32_t vr_magic;
+ u_int16_t vr_recsize;
+ u_int16_t vr_ptrsize;
+ u_int8_t vr_indirect_levels;
+ u_int8_t vr_padding0;
+ u_int16_t vr_padding1;
+};
+
+struct lvar_leaf_entry {
+ u_int32_t vle_hash;
+ u_int16_t vle_keysize;
+ u_int8_t vle_key[0];
+};
+
+enum {
+ LVAR_PAD = 4,
+ LVAR_ROUND = LVAR_PAD - 1
+};
+
+static void lfix_root(void *buf,
+ int blocksize, int keysize, int ptrsize, int recsize)
+{
+ struct iam_lfix_root *root;
+ struct dx_countlimit *limit;
+ void *entry;
+
+ root = buf;
+ *root = (typeof(*root)) {
+ .ilr_magic = cpu_to_le64(IAM_LFIX_ROOT_MAGIC),
+ .ilr_keysize = cpu_to_le16(keysize),
+ .ilr_recsize = cpu_to_le16(recsize),
+ .ilr_ptrsize = cpu_to_le16(ptrsize),
+ .ilr_indirect_levels = 0
+ };
+
+ limit = (void *)(root + 1);
+ *limit = (typeof(*limit)){
+ /*
+ * limit itself + one pointer to the leaf.
+ */
+ .count = cpu_to_le16(2),
+ .limit = (blocksize - sizeof *root) / (keysize + ptrsize)
+ };
+
+ entry = root + 1;
+ /*
+ * Skip over @limit.
+ */
+ entry += keysize + ptrsize;
+
+ /*
+ * Entry format is <key> followed by <ptr>. In the minimal tree
+ * consisting of a root and single node, <key> is a minimal possible
+ * key.
+ *
+ * XXX: this key is hard-coded to be a sequence of 0's.
+ */
+ entry += keysize;
+ /* now @entry points to <ptr> */
+ if (ptrsize == 4)
+ *(u_int32_t *)entry = cpu_to_le32(1);
+ else
+ *(u_int64_t *)entry = cpu_to_le64(1);
+}
+
+static void lfix_leaf(void *buf,
+ int blocksize, int keysize, int ptrsize, int recsize)
+{
+ struct iam_leaf_head *head;
+
+ /* form leaf */
+ head = buf;
+ *head = (struct iam_leaf_head) {
+ .ill_magic = cpu_to_le16(IAM_LEAF_HEADER_MAGIC),
+ /*
+ * Leaf contains an entry with the smallest possible key
+ * (created by zeroing).
+ */
+ .ill_count = cpu_to_le16(1),
+ };
+}
+
+static void lvar_root(void *buf,
+ int blocksize, int keysize, int ptrsize, int recsize)
+{
+ struct lvar_root *root;
+ struct dx_countlimit *limit;
+ void *entry;
+ int isize;
+
+ isize = sizeof(lvar_hash_t) + ptrsize;
+ root = buf;
+ *root = (typeof(*root)) {
+ .vr_magic = cpu_to_le32(IAM_LVAR_ROOT_MAGIC),
+ .vr_recsize = cpu_to_le16(recsize),
+ .vr_ptrsize = cpu_to_le16(ptrsize),
+ .vr_indirect_levels = 0
+ };
+
+ limit = (void *)(root + 1);
+ *limit = (typeof(*limit)){
+ /*
+ * limit itself + one pointer to the leaf.
+ */
+ .count = cpu_to_le16(2),
+ .limit = (blocksize - sizeof *root) / isize
+ };
+
+ entry = root + 1;
+ /*
+ * Skip over @limit.
+ */
+ entry += isize;
+
+ /*
+ * Entry format is <key> followed by <ptr>. In the minimal tree
+ * consisting of a root and single node, <key> is a minimal possible
+ * key.
+ *
+ * XXX: this key is hard-coded to be a sequence of 0's.
+ */
+ entry += sizeof(lvar_hash_t);
+ /* now @entry points to <ptr> */
+ if (ptrsize == 4)
+ *(u_int32_t *)entry = cpu_to_le32(1);
+ else
+ *(u_int64_t *)entry = cpu_to_le64(1);
+}
+
+static int lvar_esize(int namelen, int recsize)
+{
+ return (offsetof(struct lvar_leaf_entry, vle_key) +
+ namelen + recsize + LVAR_ROUND) & ~LVAR_ROUND;
+}
+
+static void lvar_leaf(void *buf,
+ int blocksize, int keysize, int ptrsize, int recsize)
+{
+ struct lvar_leaf_header *head;
+
+ /* form leaf */
+ head = buf;
+ *head = (typeof(*head)) {
+ .vlh_magic = cpu_to_le16(IAM_LVAR_LEAF_MAGIC),
+ .vlh_used = cpu_to_le16(sizeof *head + lvar_esize(0, recsize))
+ };
+}
+
+enum iam_fmt_t {
+ FMT_LFIX,
+ FMT_LVAR
+};
+
int main(int argc, char **argv)
{
int rc;
int ptrsize = 4;
int verbose = 0;
void *buf;
-
- struct iam_lfix_root *root;
- struct iam_leaf_head *head;
- struct dx_countlimit *limit;
- void *entry;
+ char *fmtstr = "lfix";
+ enum iam_fmt_t fmt;
do {
- opt = getopt(argc, argv, "hb:k:r:p:v");
+ opt = getopt(argc, argv, "hb:k:r:p:vf:");
switch (opt) {
case 'v':
verbose++;
case 'p':
ptrsize = atoi(optarg);
break;
+ case 'f':
+ fmtstr = optarg;
+ break;
case '?':
default:
fprintf(stderr, "Unable to parse options.");
fprintf(stderr, "Too large (record, key) or too small block\n");
return 1;
}
+
+ if (!strcmp(fmtstr, "lfix"))
+ fmt = FMT_LFIX;
+ else if (!strcmp(fmtstr, "lvar"))
+ fmt = FMT_LVAR;
+ else {
+ fprintf(stderr, "Wrong format `%s'\n", fmtstr);
+ return 1;
+ }
+
if (verbose > 0) {
fprintf(stderr,
- "key: %i, rec: %i, ptr: %i, block: %i\n",
- keysize, recsize, ptrsize, blocksize);
+ "fmt: %s, key: %i, rec: %i, ptr: %i, block: %i\n",
+ fmtstr, keysize, recsize, ptrsize, blocksize);
}
buf = malloc(blocksize);
if (buf == NULL) {
return 1;
}
- root = memset(buf, 0, blocksize);
+ memset(buf, 0, blocksize);
- *root = (typeof(*root)) {
- .ilr_magic = cpu_to_le64(IAM_LFIX_ROOT_MAGIC),
- .ilr_keysize = cpu_to_le16(keysize),
- .ilr_recsize = cpu_to_le16(recsize),
- .ilr_ptrsize = cpu_to_le16(ptrsize),
- .ilr_indirect_levels = 0
- };
-
- limit = (void *)(root + 1);
- *limit = (typeof(*limit)){
- /*
- * limit itself + one pointer to the leaf.
- */
- .count = cpu_to_le16(2),
- .limit = (blocksize -
- sizeof(struct iam_lfix_root)) / (keysize + ptrsize)
- };
-
- entry = root + 1;
- /*
- * Skip over @limit.
- */
- entry += keysize + ptrsize;
-
- /*
- * Entry format is <key> followed by <ptr>. In the minimal tree
- * consisting of a root and single node, <key> is a minimal possible
- * key.
- *
- * XXX: this key is hard-coded to be a sequence of 0's.
- */
- entry += keysize;
- /* now @entry points to <ptr> */
- if (ptrsize == 4)
- *(u_int32_t *)entry = cpu_to_le32(1);
+ if (fmt == FMT_LFIX)
+ lfix_root(buf, blocksize, keysize, ptrsize, recsize);
else
- *(u_int64_t *)entry = cpu_to_le64(1);
+ lvar_root(buf, blocksize, keysize, ptrsize, recsize);
+
rc = write(1, buf, blocksize);
if (rc != blocksize) {
fprintf(stderr, "Unable to write root node: %m (%i)\n", rc);
}
/* form leaf */
- head = memset(buf, 0, blocksize);
- *head = (struct iam_leaf_head) {
- .ill_magic = cpu_to_le16(IAM_LEAF_HEADER_MAGIC),
- /*
- * Leaf contains an entry with the smallest possible key
- * (created by zeroing).
- */
- .ill_count = cpu_to_le16(1),
- };
+ memset(buf, 0, blocksize);
+
+ if (fmt == FMT_LFIX)
+ lfix_leaf(buf, blocksize, keysize, ptrsize, recsize);
+ else
+ lvar_leaf(buf, blocksize, keysize, ptrsize, recsize);
rc = write(1, buf, blocksize);
if (rc != blocksize) {