From ebc9f0da9e0d2fe90a4f9a820114d462fdf13178 Mon Sep 17 00:00:00 2001 From: Ben Johnson Date: Wed, 8 Jan 2014 08:06:17 -0700 Subject: Basic types. --- bucket.go | 21 +++++++++++++++++++++ const.go | 15 +++++++++++++++ cursor.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ db.go | 19 +++++++++++++++++++ error.go | 30 ++++++++++++++++++++++++++++++ info.go | 10 ++++++++++ meta.go | 32 ++++++++++++++++++++++++++++++++ node.go | 40 ++++++++++++++++++++++++++++++++++++++++ page.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ reader.go | 5 +++++ stat.go | 10 ++++++++++ transaction.go | 33 +++++++++++++++++++++++++++++++++ warn.go | 14 ++++++++++++++ xcursor.go | 8 ++++++++ 14 files changed, 325 insertions(+) create mode 100644 bucket.go create mode 100644 const.go create mode 100644 cursor.go create mode 100644 db.go create mode 100644 error.go create mode 100644 info.go create mode 100644 meta.go create mode 100644 node.go create mode 100644 page.go create mode 100644 reader.go create mode 100644 stat.go create mode 100644 transaction.go create mode 100644 warn.go create mode 100644 xcursor.go diff --git a/bucket.go b/bucket.go new file mode 100644 index 0000000..16f8be3 --- /dev/null +++ b/bucket.go @@ -0,0 +1,21 @@ +package bolt + +// TODO: #define MDB_VALID 0x8000 /**< DB handle is valid, for me_dbflags */ +// TODO: #define PERSISTENT_FLAGS (0xffff & ~(MDB_VALID)) +// TODO: #define VALID_FLAGS (MDB_REVERSEKEY|MDB_DUPSORT|MDB_INTEGERKEY|MDB_DUPFIXED|MDB_INTEGERDUP|MDB_REVERSEDUP|MDB_CREATE) +// TODO: #define FREE_DBI 0 +// TODO: #define MAIN_DBI 1 + +type Bucket interface { +} + +type bucket struct { + pad int + flags int + depth int + branchPageCount int + leafPageCount int + overflowPageCount int + entryCount int + rootID int +} diff --git a/const.go b/const.go new file mode 100644 index 0000000..3bbb8dc --- /dev/null +++ b/const.go @@ -0,0 +1,15 @@ +package bolt + +const Version = 1 + +const magic int32 = 0xBEEFC0DE + +const ( + MaxKeySize = 511 + MaxDataSize = 0xffffffff +) + +const ( + DefaultMapSize = 1048576 + DefaultReaderCount = 126 +) diff --git a/cursor.go b/cursor.go new file mode 100644 index 0000000..8399b88 --- /dev/null +++ b/cursor.go @@ -0,0 +1,44 @@ +package bolt + +// TODO: #define CURSOR_STACK 32 + +// TODO: #define C_INITIALIZED 0x01 /**< cursor has been initialized and is valid */ +// TODO: #define C_EOF 0x02 /**< No more data */ +// TODO: #define C_SUB 0x04 /**< Cursor is a sub-cursor */ +// TODO: #define C_DEL 0x08 /**< last op was a cursor_del */ +// TODO: #define C_SPLITTING 0x20 /**< Cursor is in page_split */ +// TODO: #define C_UNTRACK 0x40 /**< Un-track cursor when closing */ + +type Cursor interface { + First() error + FirstDup() error + Get() ([]byte, []byte, error) + GetRange() ([]byte, []byte, error) + Current() ([]byte, []byte, error) + Last() + LastDup() + Next() ([]byte, []byte, error) + NextDup() ([]byte, []byte, error) + NextNoDup() ([]byte, []byte, error) + Prev() ([]byte, []byte, error) + PrevDup() ([]byte, []byte, error) + PrevNoDup() ([]byte, []byte, error) + Set() ([]byte, []byte, error) + SetRange() ([]byte, []byte, error) +} + +type cursor struct { + flags int + next *cursor + backup *cursor + xcursor *xcursor + transaction *transaction + bucketId int + bucket *bucket + bucketx *bucketx + bucketFlag int + snum int + top int + page []*page + ki []int /**< stack of page indices */ +} diff --git a/db.go b/db.go new file mode 100644 index 0000000..914cd18 --- /dev/null +++ b/db.go @@ -0,0 +1,19 @@ +package bolt + +const ( + NoSync = iota + NoMetaSync + DupSort + IntegerKey + IntegerDupKey +) + +type DB interface { +} + +type db struct { +} + +func NewDB() DB { + return &db{} +} diff --git a/error.go b/error.go new file mode 100644 index 0000000..caed282 --- /dev/null +++ b/error.go @@ -0,0 +1,30 @@ +package bolt + +var ( + KeyExistError = &Error{"Key/data pair already exists"} + NotFoundError = &Error{"No matching key/data pair found"} + PageNotFoundError = &Error{"Requested page not found"} + CorruptedError = &Error{"Located page was wrong type"} + PanicError = &Error{"Update of meta page failed"} + VersionMismatchError = &Error{"Database environment version mismatch"} + InvalidError = &Error{"File is not an MDB file"} + MapFullError = &Error{"Environment mapsize limit reached"} + BucketFullError = &Error{"Environment maxdbs limit reached"} + ReadersFullError = &Error{"Environment maxreaders limit reached"} + TransactionFullError = &Error{"Transaction has too many dirty pages - transaction too big"} + CursorFullError = &Error{"Internal error - cursor stack limit reached"} + PageFullError = &Error{"Internal error - page has no more space"} + MapResizedError = &Error{"Database contents grew beyond environment mapsize"} + IncompatibleError = &Error{"Operation and DB incompatible, or DB flags changed"} + BadReaderSlotError = &Error{"Invalid reuse of reader locktable slot"} + BadTransactionError = &Error{"Transaction cannot recover - it must be aborted"} + BadValueSizeError = &Error{"Too big key/data, key is empty, or wrong DUPFIXED size"} +) + +type Error struct { + message string +} + +func (e *Error) Error() { + return e.message +} diff --git a/info.go b/info.go new file mode 100644 index 0000000..d9642a5 --- /dev/null +++ b/info.go @@ -0,0 +1,10 @@ +package bolt + +// info contains information about the database. +type info struct { + MapSize int + LastPageID int + LastTransactionID int + MaxReaders int + ReaderCount int +} diff --git a/meta.go b/meta.go new file mode 100644 index 0000000..defa85b --- /dev/null +++ b/meta.go @@ -0,0 +1,32 @@ +package bolt + +type meta struct { + magic int32 + version int32 + mapSize int + free *bucket + main *bucket + lastPageNumber int + transactionID int +} + +// TODO: #define mm_psize mm_dbs[0].md_pad +// TODO: #define mm_flags mm_dbs[0].md_flags + +// TODO: +// typedef union MDB_metabuf { +// MDB_page mb_page; +// struct { +// char mm_pad[PAGEHDRSZ]; +// MDB_meta mm_meta; +// } mb_metabuf; +// } MDB_metabuf; + +// TODO: +// typedef struct MDB_dbx { +// MDB_val md_name; /**< name of the database */ +// MDB_cmp_func *md_cmp; /**< function for comparing keys */ +// MDB_cmp_func *md_dcmp; /**< function for comparing data items */ +// MDB_rel_func *md_rel; /**< user relocate function */ +// void *md_relctx; /**< user-provided context for md_rel */ +// } MDB_dbx; diff --git a/node.go b/node.go new file mode 100644 index 0000000..38b0293 --- /dev/null +++ b/node.go @@ -0,0 +1,40 @@ +package bolt + +const ( + bigNode = 0x01 + subNode = 0x02 + dupNode = 0x04 +) + +type node struct { + lo int + hi int + flags int + keySize int + data []byte +} + +func (n *node) setFlags(f int) { + // Valid flags: (F_DUPDATA|F_SUBDATA|MDB_RESERVE|MDB_APPEND) + // TODO +} + +func (n *node) size() int { + return 0 // TODO: offsetof(MDB_node, mn_data) +} + +// TODO: #define INDXSIZE(k) (NODESIZE + ((k) == NULL ? 0 : (k)->mv_size)) +// TODO: #define LEAFSIZE(k, d) (NODESIZE + (k)->mv_size + (d)->mv_size) +// TODO: #define NODEPTR(p, i) ((MDB_node *)((char *)(p) + (p)->mp_ptrs[i])) +// TODO: #define NODEKEY(node) (void *)((node)->mn_data) +// TODO: #define NODEDATA(node) (void *)((char *)(node)->mn_data + (node)->mn_ksize) +// TODO: #define NODEPGNO(node) ((node)->mn_lo | ((pgno_t) (node)->mn_hi << 16) | (PGNO_TOPWORD ? ((pgno_t) (node)->mn_flags << PGNO_TOPWORD) : 0)) +// TODO: #define SETPGNO(node,pgno) do { (node)->mn_lo = (pgno) & 0xffff; (node)->mn_hi = (pgno) >> 16; if (PGNO_TOPWORD) (node)->mn_flags = (pgno) >> PGNO_TOPWORD; } while(0) +// TODO: #define NODEDSZ(node) ((node)->mn_lo | ((unsigned)(node)->mn_hi << 16)) +// TODO: #define SETDSZ(node,size) do { (node)->mn_lo = (size) & 0xffff; (node)->mn_hi = (size) >> 16;} while(0) +// TODO: #define NODEKSZ(node) ((node)->mn_ksize) + +// TODO: #define LEAF2KEY(p, i, ks) ((char *)(p) + PAGEHDRSZ + ((i)*(ks))) + +// TODO: #define MDB_GET_KEY(node, keyptr) { if ((keyptr) != NULL) { (keyptr)->mv_size = NODEKSZ(node); (keyptr)->mv_data = NODEKEY(node); } } +// TODO: #define MDB_GET_KEY2(node, key) { key.mv_size = NODEKSZ(node); key.mv_data = NODEKEY(node); } diff --git a/page.go b/page.go new file mode 100644 index 0000000..3f1e6b3 --- /dev/null +++ b/page.go @@ -0,0 +1,44 @@ +package bolt + +import ( + "unsafe" +) + +const MinPageKeys = 2 +const FillThreshold = 250 // 25% + +const ( + BranchPage = 0x01 + LeafPage = 0x02 + OverflowPage = 0x04 + MetaPage = 0x08 + DirtyPage = 0x10 /**< dirty page, also set for #P_SUBP pages */ + SubPage = 0x40 + KeepPage = 0x8000 /**< leave this page alone during spill */ +) + +type page struct { + header struct { + id int + next *page // (?) + lower int + upper int + overflowPageCount int + } + metadata []byte +} + +// nodeCount returns the number of nodes on the page. +func (p *page) nodeCount() int { + return 0 // (p.header.lower - unsafe.Sizeof(p.header) >> 1 +} + +// remainingSize returns the number of bytes left in the page. +func (p *page) remainingSize() int { + return p.header.upper - p.header.lower +} + +// remainingSize returns the number of bytes left in the page. +func (p *page) remainingSize() int { + return p.header.upper - p.header.lower +} diff --git a/reader.go b/reader.go new file mode 100644 index 0000000..c51517c --- /dev/null +++ b/reader.go @@ -0,0 +1,5 @@ +package bolt + +type reader struct { + int transactionID +} diff --git a/stat.go b/stat.go new file mode 100644 index 0000000..b01fa99 --- /dev/null +++ b/stat.go @@ -0,0 +1,10 @@ +package bolt + +type Stat struct { + PageSize int + Depth int + BranchPageCount int + LeafPageCount int + OverflowPageCount int + EntryCount int +} diff --git a/transaction.go b/transaction.go new file mode 100644 index 0000000..74118d1 --- /dev/null +++ b/transaction.go @@ -0,0 +1,33 @@ +package bolt + +// TODO: #define DB_DIRTY 0x01 /**< DB was modified or is DUPSORT data */ +// TODO: #define DB_STALE 0x02 /**< Named-DB record is older than txnID */ +// TODO: #define DB_NEW 0x04 /**< Named-DB handle opened in this txn */ +// TODO: #define DB_VALID 0x08 /**< DB handle is valid, see also #MDB_VALID */ + +// TODO: #define MDB_TXN_RDONLY 0x01 /**< read-only transaction */ +// TODO: #define MDB_TXN_ERROR 0x02 /**< an error has occurred */ +// TODO: #define MDB_TXN_DIRTY 0x04 /**< must write, even if dirty list is empty */ +// TODO: #define MDB_TXN_SPILLS 0x08 /**< txn or a parent has spilled pages */ + +type Transaction interface { +} + +type transaction struct { + id int + flags int + db *db + parent *transaction + child *transaction + nextPageNumber int + freePages []int + spillPages []int + dirtyList []int + reader *reader + // TODO: bucketxs []*bucketx + buckets []*bucket + bucketFlags []int + cursors []*cursor + // Implicit from slices? TODO: MDB_dbi mt_numdbs; + mt_dirty_room int +} diff --git a/warn.go b/warn.go new file mode 100644 index 0000000..7e9a2a7 --- /dev/null +++ b/warn.go @@ -0,0 +1,14 @@ +package bolt + +import ( + "fmt" + "os" +) + +func warn(v ...interface{}) { + fmt.Fprintln(os.Stderr, v...) +} + +func warnf(msg string, v ...interface{}) { + fmt.Fprintf(os.Stderr, msg, v...) +} diff --git a/xcursor.go b/xcursor.go new file mode 100644 index 0000000..fa0e915 --- /dev/null +++ b/xcursor.go @@ -0,0 +1,8 @@ +package bolt + +type xcursor struct { + cursor cursor + bucket *bucket + bucketx *bucketx + bucketFlag int +} -- cgit v1.2.3