diff options
-rw-r--r-- | src/dedo.go | 112 | ||||
-rw-r--r-- | tests/dedo.go | 58 |
2 files changed, 85 insertions, 85 deletions
diff --git a/src/dedo.go b/src/dedo.go index 39e1269..dedeaa9 100644 --- a/src/dedo.go +++ b/src/dedo.go @@ -14,7 +14,7 @@ /// /// == Basics /// -/// There are only a few types in Dedo: DB, Bucket, Tx, and Cursor. The DB is +/// There are only a few types in Dedo: DB, Bucket, transactionT, and Cursor. The DB is /// a collection of buckets and is represented by a single file on disk. A /// bucket is a collection of unique keys that are associated with values. /// @@ -106,7 +106,7 @@ type bucket struct { /// database. Keys aren't unique across different buckets. type Bucket struct { ref *bucket - tx *Tx /// the associated transaction + tx *transactionT /// the associated transaction buckets map[string]*Bucket /// subbucket cache page *page /// inline page reference rootNode *node /// materialized node for the root page @@ -182,8 +182,8 @@ type DB struct { meta1 *meta pageSize int opened bool - rwtx *Tx - txs []*Tx + rwtx *transactionT + txs []*transactionT freelist *freelist magic uint32 @@ -295,7 +295,7 @@ type pgids []pgid /// txid represents the internal transaction identifier. type txid uint64 -/// Tx represents a read-only or read/write transaction on the database. +/// transactionT represents a read-only or read/write transaction on the database. /// Read-only transactions can be used for retrieving values for keys and /// creating cursors. Read/write transactions can create and remove buckets /// and create and remove keys. @@ -304,7 +304,7 @@ type txid uint64 /// them. Pages can not be reclaimed by the writer until no more transactions /// are using them. A long running read transaction can cause the database to /// quickly grow. -type Tx struct { +type transactionT struct { writable bool db *DB meta *meta @@ -422,7 +422,7 @@ var ( /// - /// These errors can occur when beginning or committing a Tx. + /// These errors can occur when beginning or committing a transactionT. /// /// ErrTxNotWritable is returned when performing a write operation on a @@ -573,7 +573,7 @@ func madvise(b []byte, advice int) (err error) { } /// newBucket() returns a new bucket associated with a transaction. -func newBucket(tx *Tx) Bucket { +func newBucket(tx *transactionT) Bucket { b := Bucket{tx: tx} if tx.writable { b.buckets = make(map[string]*Bucket) @@ -2010,7 +2010,7 @@ func (db *DB) close() error { /// IMPORTANT: You must close read-only transactions after you are finished or /// else the database will not reclaim old pages. -func (db *DB) beginTx() (*Tx, error) { +func (db *DB) beginTx() (*transactionT, error) { // Lock the meta pages while we initialize the transaction. We obtain // the meta lock before the mmap lock because that's the order that the // write transaction will obtain them. @@ -2029,7 +2029,7 @@ func (db *DB) beginTx() (*Tx, error) { } // Create a transaction associated with the database. - t := &Tx{} + t := &transactionT{} t.init(db) // Keep track of transaction until it closes. @@ -2041,7 +2041,7 @@ func (db *DB) beginTx() (*Tx, error) { return t, nil } -func (db *DB) beginRWTx() (*Tx, error) { +func (db *DB) beginRWTx() (*transactionT, error) { // Obtain writer lock. This is released by the transaction when it // closes. This enforces only one writer transaction at a time. db.rwlock.Lock() @@ -2058,7 +2058,7 @@ func (db *DB) beginRWTx() (*Tx, error) { } // Create a transaction associated with the database. - t := &Tx{writable: true} + t := &transactionT{writable: true} t.init(db) db.rwtx = t @@ -2077,7 +2077,7 @@ func (db *DB) beginRWTx() (*Tx, error) { } /// DB.removeTx() removes a transaction from the database. -func (db *DB) removeTx(tx *Tx) { +func (db *DB) removeTx(tx *transactionT) { // Release the read lock on the mmap. db.mmaplock.RUnlock() @@ -3458,8 +3458,8 @@ func mergepgids(dst, a, b pgids) { _ = append(merged, follow...) } -/// Tx.init() initializes the transaction. -func (tx *Tx) init(db *DB) { +/// transactionT.init() initializes the transaction. +func (tx *transactionT) init(db *DB) { tx.db = db tx.pages = nil @@ -3480,58 +3480,58 @@ func (tx *Tx) init(db *DB) { } } -/// Tx.ID() returns the transaction id. -func (tx *Tx) ID() int { +/// transactionT.ID() returns the transaction id. +func (tx *transactionT) ID() int { return int(tx.meta.txid) } -/// Tx.Size() returns current database size in bytes as seen by this +/// transactionT.Size() returns current database size in bytes as seen by this /// transaction. -func (tx *Tx) Size() int64 { +func (tx *transactionT) Size() int64 { return int64(tx.meta.pgid) * int64(tx.db.pageSize) } -/// Tx.Cursor() creates a cursor associated with the root bucket. All items in +/// transactionT.Cursor() creates a cursor associated with the root bucket. All items in /// the cursor will return a nil value because all root bucket keys point to /// buckets. The cursor is only valid as long as the transaction is open. Do /// not use a cursor after the transaction is closed. -func (tx *Tx) Cursor() *Cursor { +func (tx *transactionT) Cursor() *Cursor { return tx.root.Cursor() } -/// Tx.Bucket() retrieves a bucket by name. Returns nil if the bucket does not +/// transactionT.Bucket() retrieves a bucket by name. Returns nil if the bucket does not /// exist. The bucket instance is only valid for the lifetime of the /// transaction. -func (tx *Tx) Bucket(name []byte) *Bucket { +func (tx *transactionT) Bucket(name []byte) *Bucket { return tx.root.Bucket(name) } -/// Tx.CreateBucket() creates a new bucket. Returns an error if the bucket +/// transactionT.CreateBucket() creates a new bucket. Returns an error if the bucket /// already exists, if the bucket name is blank, or if the bucket name is too /// long. The bucket instance is only valid for the lifetime of the /// transaction. -func (tx *Tx) CreateBucket(name []byte) (*Bucket, error) { +func (tx *transactionT) CreateBucket(name []byte) (*Bucket, error) { return tx.root.CreateBucket(name) } -/// Tx.CreateBucketIfNotExists() creates a new bucket if it doesn't already +/// transactionT.CreateBucketIfNotExists() creates a new bucket if it doesn't already /// exist. Returns an error if the bucket name is blank, or if the bucket name /// is too long. The bucket instance is only valid for the lifetime of the /// transaction. -func (tx *Tx) CreateBucketIfNotExists(name []byte) (*Bucket, error) { +func (tx *transactionT) CreateBucketIfNotExists(name []byte) (*Bucket, error) { return tx.root.CreateBucketIfNotExists(name) } -/// Tx.DeleteBucket() deletes a bucket. Returns an error if the bucket cannot +/// transactionT.DeleteBucket() deletes a bucket. Returns an error if the bucket cannot /// be found or if the key represents a non-bucket value. -func (tx *Tx) DeleteBucket(name []byte) error { +func (tx *transactionT) DeleteBucket(name []byte) error { return tx.root.DeleteBucket(name) } -/// Tx.ForEach() executes a function for each bucket in the root. If the +/// transactionT.ForEach() executes a function for each bucket in the root. If the /// provided function returns an error then the iteration is stopped and the /// error is returned to the caller. -func (tx *Tx) ForEach(fn func(name []byte, b *Bucket) error) error { +func (tx *transactionT) ForEach(fn func(name []byte, b *Bucket) error) error { return tx.root.ForEach(func(k, v []byte) error { err := fn(k, tx.root.Bucket(k)) if err != nil { @@ -3541,16 +3541,16 @@ func (tx *Tx) ForEach(fn func(name []byte, b *Bucket) error) error { }) } -/// Tx.OnCommit() adds a handler function to be executed after the transaction +/// transactionT.OnCommit() adds a handler function to be executed after the transaction /// successfully commits. -func (tx *Tx) OnCommit(fn func()) { +func (tx *transactionT) OnCommit(fn func()) { tx.commitHandlers = append(tx.commitHandlers, fn) } -/// Tx.commit() writes all changes to disk and updates the meta page. Returns -/// an error if a disk write error occurs, or if Tx.commiti() is called on a +/// transactionT.commit() writes all changes to disk and updates the meta page. Returns +/// an error if a disk write error occurs, or if transactionT.commiti() is called on a /// read-only transaction. -func (tx *Tx) commit() error { +func (tx *transactionT) commit() error { if tx.db == nil { return ErrTxClosed } else if !tx.writable { @@ -3626,9 +3626,9 @@ func (tx *Tx) commit() error { return nil } -/// Tx.rollback() closes the transaction and ignores all previous updates. +/// transactionT.rollback() closes the transaction and ignores all previous updates. /// Read-only transactions must be rolled back and not committed. -func (tx *Tx) rollback() error { +func (tx *transactionT) rollback() error { if tx.db == nil { return ErrTxClosed } @@ -3636,7 +3636,7 @@ func (tx *Tx) rollback() error { return nil } -func (tx *Tx) doRollback() { +func (tx *transactionT) doRollback() { if tx.db == nil { return } @@ -3647,7 +3647,7 @@ func (tx *Tx) doRollback() { tx.close() } -func (tx *Tx) close() { +func (tx *transactionT) close() { if tx.db == nil { return } @@ -3666,9 +3666,9 @@ func (tx *Tx) close() { tx.pages = nil } -/// Tx.WriteTo() writes the entire database to a writer. If err == nil then +/// transactionT.WriteTo() writes the entire database to a writer. If err == nil then /// exactly tx.Size() bytes will be written into the writer. -func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) { +func (tx *transactionT) WriteTo(w io.Writer) (n int64, err error) { f, err := os.OpenFile(tx.db.path, os.O_RDONLY, 0) if err != nil { return 0, err @@ -3716,7 +3716,7 @@ func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) { return n, f.Close() } -/// Tx.Check() performs several consistency checks on the database for this +/// transactionT.Check() performs several consistency checks on the database for this /// transaction. An error is returned if any inconsistency is found. /// /// It can be safely run concurrently on a writable transaction. However, this @@ -3724,13 +3724,13 @@ func (tx *Tx) WriteTo(w io.Writer) (n int64, err error) { /// subbuckets because of caching. This overhead can be removed if running on a /// read-only transaction, however, it is not safe to execute other writer /// transactions at the same time. -func (tx *Tx) Check() <-chan error { +func (tx *transactionT) Check() <-chan error { ch := make(chan error) go tx.check(ch) return ch } -func (tx *Tx) check(ch chan error) { +func (tx *transactionT) check(ch chan error) { // Check if any pages are double freed. freed := make(map[pgid]bool) all := make([]pgid, tx.db.freelist.count()) @@ -3773,7 +3773,7 @@ func isLeafPage(p *page) bool { return (p.flags & leafPageFlag) == 0 } -func (tx *Tx) checkBucket( +func (tx *transactionT) checkBucket( b *Bucket, reachable map[pgid]*page, freed map[pgid]bool, @@ -3829,8 +3829,8 @@ func (tx *Tx) checkBucket( }) } -/// Tx.allocate() returns a contiguous block of memory starting at a given page. -func (tx *Tx) allocate(count int) (*page, error) { +/// transactionT.allocate() returns a contiguous block of memory starting at a given page. +func (tx *transactionT) allocate(count int) (*page, error) { p, err := tx.db.allocate(count) if err != nil { return nil, err @@ -3842,8 +3842,8 @@ func (tx *Tx) allocate(count int) (*page, error) { return p, nil } -/// Tx.write() writes any dirty pages to disk. -func (tx *Tx) write() error { +/// transactionT.write() writes any dirty pages to disk. +func (tx *transactionT) write() error { // Sort pages by id. pages := make(pages, 0, len(tx.pages)) for _, p := range tx.pages { @@ -3910,8 +3910,8 @@ func (tx *Tx) write() error { return nil } -/// Tx.writeMeta() writes the meta to the disk. -func (tx *Tx) writeMeta() error { +/// transactionT.writeMeta() writes the meta to the disk. +func (tx *transactionT) writeMeta() error { // Create a temporary buffer for the meta page. buf := make([]byte, tx.db.pageSize) p := pageInBuffer(tx.db, buf, 0) @@ -3931,9 +3931,9 @@ func (tx *Tx) writeMeta() error { return nil } -/// Tx.page() returns a reference to the page with a given id. If page has been +/// transactionT.page() returns a reference to the page with a given id. If page has been /// written to then a temporary buffered page is returned. -func (tx *Tx) page(id pgid) *page { +func (tx *transactionT) page(id pgid) *page { // Check the dirty pages first. if tx.pages != nil { p, ok := tx.pages[id] @@ -3946,9 +3946,9 @@ func (tx *Tx) page(id pgid) *page { return tx.db.page(id) } -/// Tx.forEachPage() iterates over every page within a given page and executes a +/// transactionT.forEachPage() iterates over every page within a given page and executes a /// function. -func (tx *Tx) forEachPage(pgid pgid, depth int, fn func(*page, int)) { +func (tx *transactionT) forEachPage(pgid pgid, depth int, fn func(*page, int)) { p := tx.page(pgid) // Execute function. diff --git a/tests/dedo.go b/tests/dedo.go index 61ebca6..63cb64d 100644 --- a/tests/dedo.go +++ b/tests/dedo.go @@ -39,10 +39,10 @@ type pageInfoT struct{ overflowCount int } -/// Tx.copyFile() copies the entire database to file at the given path. A +/// transactionT.copyFile() copies the entire database to file at the given path. A /// reader transaction is maintained during the copy so it is safe to continue /// using the database while a copy is in progress. -func (tx *Tx) copyFile(path string, mode os.FileMode) error { +func (tx *transactionT) copyFile(path string, mode os.FileMode) error { f, err := os.OpenFile(path, os.O_RDWR | os.O_CREATE | os.O_TRUNC, mode) if err != nil { return err @@ -57,9 +57,9 @@ func (tx *Tx) copyFile(path string, mode os.FileMode) error { return f.Close() } -/// Tx.Page() returns page information for a given page number. This is only +/// transactionT.Page() returns page information for a given page number. This is only /// safe for concurrent use when used by a writable transaction. -func (tx *Tx) pageInfo(id int) (*pageInfoT, error) { +func (tx *transactionT) pageInfo(id int) (*pageInfoT, error) { if tx.db == nil { return nil, ErrTxClosed } else if pgid(id) >= tx.meta.pgid { @@ -2265,7 +2265,7 @@ func ExampleBucket_ForEach() { // A liger is awesome. } -// Ensure that a Tx cursor can seek to the appropriate keys. +// Ensure that a transactionT cursor can seek to the appropriate keys. func TestCursor_Seek(t *testing.T) { db := MustOpenDB() defer db.MustClose() @@ -2414,7 +2414,7 @@ func TestCursor_Delete(t *testing.T) { } } -// Ensure that a Tx cursor can seek to the appropriate keys when there are a +// Ensure that a transactionT cursor can seek to the appropriate keys when there are a // large number of keys. This test also checks that seek will always move // forward to the next key. // @@ -2516,7 +2516,7 @@ func TestCursor_EmptyBucket(t *testing.T) { } } -// Ensure that a Tx cursor can reverse iterate over an empty bucket without +// Ensure that a transactionT cursor can reverse iterate over an empty bucket without // error. func TestCursor_EmptyBucketReverse(t *testing.T) { db := MustOpenDB() @@ -2546,7 +2546,7 @@ func TestCursor_EmptyBucketReverse(t *testing.T) { } } -// Ensure that a Tx cursor can iterate over a single root with a couple +// Ensure that a transactionT cursor can iterate over a single root with a couple // elements. func TestCursor_Iterate_Leaf(t *testing.T) { db := MustOpenDB() @@ -2629,7 +2629,7 @@ func TestCursor_Iterate_Leaf(t *testing.T) { } } -// Ensure that a Tx cursor can iterate in reverse over a single root with a +// Ensure that a transactionT cursor can iterate in reverse over a single root with a // couple elements. func TestCursor_LeafRootReverse(t *testing.T) { db := MustOpenDB() @@ -2710,7 +2710,7 @@ func TestCursor_LeafRootReverse(t *testing.T) { } } -// Ensure that a Tx cursor can restart from the beginning. +// Ensure that a transactionT cursor can restart from the beginning. func TestCursor_Restart(t *testing.T) { db := MustOpenDB() defer db.MustClose() @@ -2822,7 +2822,7 @@ func TestCursor_First_EmptyPages(t *testing.T) { } } -// Ensure that a Tx can iterate over all elements in a bucket. +// Ensure that a transactionT can iterate over all elements in a bucket. func TestCursor_QuickCheck(t *testing.T) { f := func(items testdata) bool { db := MustOpenDB() @@ -2970,7 +2970,7 @@ func TestCursor_QuickCheck_Reverse(t *testing.T) { } } -// Ensure that a Tx cursor can iterate over subbuckets. +// Ensure that a transactionT cursor can iterate over subbuckets. func TestCursor_QuickCheck_BucketsOnly(t *testing.T) { db := MustOpenDB() defer db.MustClose() @@ -3024,7 +3024,7 @@ func TestCursor_QuickCheck_BucketsOnly(t *testing.T) { } } -// Ensure that a Tx cursor can reverse iterate over subbuckets. +// Ensure that a transactionT cursor can reverse iterate over subbuckets. func TestCursor_QuickCheck_BucketsOnly_Reverse(t *testing.T) { db := MustOpenDB() defer db.MustClose() @@ -3942,7 +3942,7 @@ func TestDB_Consistency(t *testing.T) { } err = db.Update(func(itx TransactionI) error { - tx := itx.(*Tx) + tx := itx.(*transactionT) p, _ := tx.pageInfo(0) if p == nil { t.Fatal("expected page") @@ -4630,7 +4630,7 @@ func (db *WDB) MustClose() { // are found. func (db *WDB) MustCheck() { err := db.Update(func(itx TransactionI) error { - tx := itx.(*Tx) + tx := itx.(*transactionT) // Collect all the errors. errors := []error{} for err := range tx.Check() { @@ -4676,7 +4676,7 @@ func (db *WDB) MustCheck() { func (db *WDB) CopyTempFile() { path := tempfile() err := db.View(func(snapshot SnapshotI) error { - tx := snapshot.(*Tx) + tx := snapshot.(*transactionT) return tx.copyFile(path, 0600) }) if err != nil { @@ -5013,7 +5013,7 @@ func TestNode_put(t *testing.T) { n := &node{ inodes: make(inodes, 0), bucket: &Bucket{ - tx: &Tx{ + tx: &transactionT{ meta: &meta{ pgid: 1, }, @@ -5102,7 +5102,7 @@ func TestNode_write_LeafPage(t *testing.T) { isLeaf: true, inodes: make(inodes, 0), bucket: &Bucket{ - tx: &Tx{ + tx: &transactionT{ db: &DB{}, meta: &meta{ pgid: 1, @@ -5150,7 +5150,7 @@ func TestNode_split(t *testing.T) { n := &node{ inodes: make(inodes, 0), bucket: &Bucket{ - tx: &Tx{ + tx: &transactionT{ db: &DB{}, meta: &meta{ pgid: 1, @@ -5186,7 +5186,7 @@ func TestNode_split_MinKeys(t *testing.T) { n := &node{ inodes: make(inodes, 0), bucket: &Bucket{ - tx: &Tx{ + tx: &transactionT{ db: &DB{}, meta: &meta{ pgid: 1, @@ -5211,7 +5211,7 @@ func TestNode_split_SinglePage(t *testing.T) { n := &node{ inodes: make(inodes, 0), bucket: &Bucket{ - tx: &Tx{ + tx: &transactionT{ db: &DB{}, meta: &meta{ pgid: 1, @@ -5515,7 +5515,7 @@ func testSimulate(t *testing.T, threadCount, parallelism int) { defer wg.Done() // Start transaction. - var tx *Tx + var tx *transactionT var err error if writable { tx, err = db.beginRWTx() @@ -5573,10 +5573,10 @@ func testSimulate(t *testing.T, threadCount, parallelism int) { wg.Wait() } -type simulateHandler func(tx *Tx, qdb *QuickDB) +type simulateHandler func(tx *transactionT, qdb *QuickDB) // Retrieves a key from the database and verifies that it is what is expected. -func simulateGetHandler(tx *Tx, qdb *QuickDB) { +func simulateGetHandler(tx *transactionT, qdb *QuickDB) { // Randomly retrieve an existing exist. keys := qdb.Rand() if len(keys) == 0 { @@ -5618,7 +5618,7 @@ func simulateGetHandler(tx *Tx, qdb *QuickDB) { } // Inserts a key into the database. -func simulatePutHandler(tx *Tx, qdb *QuickDB) { +func simulatePutHandler(tx *transactionT, qdb *QuickDB) { var err error keys, value := randKeys(), randValue() @@ -5919,7 +5919,7 @@ func TestTx_CreateBucket_ErrTxNotWritable(t *testing.T) { defer os.Remove(db.Path()) err := db.View(func(snapshot SnapshotI) error { - tx := snapshot.(*Tx) + tx := snapshot.(*transactionT) _, err := tx.CreateBucket([]byte("foo")) if err != ErrTxNotWritable { t.Fatalf("unexpected error: %s", err) @@ -5954,7 +5954,7 @@ func TestTx_CreateBucket_ErrTxClosed(t *testing.T) { } } -// Ensure that a Tx can retrieve a bucket. +// Ensure that a transactionT can retrieve a bucket. func TestTx_Bucket(t *testing.T) { db := MustOpenDB() defer db.MustClose() @@ -5977,7 +5977,7 @@ func TestTx_Bucket(t *testing.T) { } } -// Ensure that a Tx retrieving a non-existent key returns nil. +// Ensure that a transactionT retrieving a non-existent key returns nil. func TestTx_Get_NotFound(t *testing.T) { db := MustOpenDB() defer db.MustClose() @@ -6247,7 +6247,7 @@ func TestTx_DeleteBucket_ReadOnly(t *testing.T) { defer os.Remove(db.Path()) err := db.View(func(snapshot SnapshotI) error { - tx := snapshot.(*Tx) + tx := snapshot.(*transactionT) err := tx.DeleteBucket([]byte("foo")) if err != ErrTxNotWritable { t.Fatalf("unexpected error: %s", err) |