#include #include #include "mdb.h" #include "impl.h" /* macros from hjfs */ #define GET8(x) {x = *p++;} #define GET16(x) {x = *p++; x |= *p++ << 8;} #define GET24(x) {x = *p++; x |= *p++ << 8; x |= *p++ << 16;} #define GET32(x) {x = *p++; x |= *p++ << 8; x |= *p++ << 16; x |= *p++ << 24;} #define GET64(x) \ {x = (uvlong) *p++; \ x |= (uvlong) *p++ << 8; \ x |= (uvlong) *p++ << 16; \ x |= (uvlong) *p++ << 24; \ x |= (uvlong) *p++ << 32; \ x |= (uvlong) *p++ << 40; \ x |= (uvlong) *p++ << 48; \ x |= (uvlong) *p++ << 56;} #define GETS(x, n) {memcpy(x, p, n); p += n;} #define PUT8(x) {*p++ = x;} #define PUT16(x) {*p++ = x; *p++ = x >> 8;} #define PUT24(x) {*p++ = x; *p++ = x >> 8; *p++ = x >> 16;} #define PUT32(x) {*p++ = x; *p++ = x >> 8; *p++ = x >> 16; *p++ = x >> 24;} #define PUT64(x) \ {*p++ = x; \ *p++ = x >> 8; \ *p++ = x >> 16; \ *p++ = x >> 24; \ *p++ = x >> 32; \ *p++ = x >> 40; \ *p++ = x >> 48; \ *p++ = x >> 56;} #define PUTS(x, n) {memcpy(p, x, n); p += n;} /* * pack page into block * TODO: abort when reading corrupt data */ int mdb_unpack(MDB *db, Page *page, uchar b[BLOCK]) { int i; uchar *p; Key *k; KeyPair *kp; p = b; GET16(page->type); GET16(page->pad); switch(page->type){ case T_META: GET32(page->meta.magic); GET32(page->meta.freelist); GET32(page->meta.root); GET32(page->meta.pgid); break; case T_FREELIST: GET32(page->free.next); GET32(page->free.count); for(i = 0; i < page->free.count; i++) GET32(page->free.ids[i]); break; case T_BRANCH: GET32(page->branch.n); for(i = 0; i < page->branch.n; i++){ k = &page->branch.keys[i]; GET8(k->len); GETS(k->data, k->len); } for(i = 0; i < page->branch.n+1; i++) GET32(page->branch.child[i]); break; case T_LEAF: GET32(page->leaf.n); GET32(page->leaf.next); for(i = 0; i < page->leaf.n; i++){ kp = &page->leaf.keypairs[i]; GET8(kp->key.len); GETS(kp->key.data, kp->key.len); GET32(kp->pid); GET32(kp->length); } break; case T_DATA: GET32(page->data.next); GET16(page->data.length); GETS(page->data.value, page->data.length); break; default: corrupt: fprint(2, "mdb_unpack: page %ud: unknown page type %ud\n", page->id, page->type); mdb_error_corrupt(db); } assert((p - b) <= BLOCK); return p - b; } int mdb_pack(MDB *db, Page *page, uchar b[BLOCK]) { int i; uchar *p; Key *k; KeyPair *kp; USED(db); p = b; memset(p, 0, BLOCK); PUT16(page->type); PUT16(page->pad); switch(page->type){ case T_META: PUT32(page->meta.magic); PUT32(page->meta.freelist); PUT32(page->meta.root); PUT32(page->meta.pgid); break; case T_FREELIST: PUT32(page->free.next); PUT32(page->free.count); for(i = 0; i < page->free.count; i++) PUT32(page->free.ids[i]); break; case T_BRANCH: PUT32(page->branch.n); for(i = 0; i < page->branch.n; i++){ k = &page->branch.keys[i]; PUT8(k->len); PUTS(k->data, k->len); } for(i = 0; i < page->branch.n+1; i++) PUT32(page->branch.child[i]); break; case T_LEAF: PUT32(page->leaf.n); PUT32(page->leaf.next); for(i = 0; i < page->leaf.n; i++){ kp = &page->leaf.keypairs[i]; PUT8(kp->key.len); PUTS(kp->key.data, kp->key.len); PUT32(kp->pid); PUT32(kp->length); } break; case T_DATA: PUT32(page->data.next); PUT16(page->data.length); PUTS(page->data.value, page->data.length); break; default: abort(); } assert((p - b) <= BLOCK); return p - b; }