aboutsummaryrefslogtreecommitdiff
path: root/transaction.go
diff options
context:
space:
mode:
Diffstat (limited to 'transaction.go')
-rw-r--r--transaction.go115
1 files changed, 32 insertions, 83 deletions
diff --git a/transaction.go b/transaction.go
index 8371624..07665ee 100644
--- a/transaction.go
+++ b/transaction.go
@@ -1,7 +1,6 @@
package bolt
import (
- "strings"
"unsafe"
)
@@ -20,11 +19,12 @@ const (
type txnid uint64
type Transaction struct {
- id int
- db *DB
- meta *meta
- sys Bucket
- buckets map[string]*Bucket
+ id int
+ db *DB
+ meta *meta
+ sys Bucket
+ buckets map[string]*Bucket
+ pages map[pgid]*page
}
// init initializes the transaction and associates it with a database.
@@ -32,6 +32,7 @@ func (t *Transaction) init(db *DB, meta *meta) {
t.db = db
t.meta = meta
t.buckets = make(map[string]*Bucket)
+ t.pages = nil
t.sys.transaction = t
t.sys.bucket = &t.meta.sys
}
@@ -47,27 +48,21 @@ func (t *Transaction) DB() *DB {
// Bucket retrieves a bucket by name.
func (t *Transaction) Bucket(name string) (*Bucket, error) {
- return t.bucket(name)
-}
-
-func (t *Transaction) bucket(name string) (*Bucket, error) {
- // Return bucket if it's already been looked up.
+ // Return cached reference if it's already been looked up.
if b := t.buckets[name]; b != nil {
return b, nil
}
// Retrieve bucket data from the system bucket.
- data, err := c.get(&t.sys, []byte(name))
- if err != nil {
- return nil, err
- } else if data == nil {
- return nil, &Error{"bucket not found", nil}
+ value := t.get(&t.sys, []byte(name))
+ if value == nil {
+ return nil
}
// Create a bucket that overlays the data.
b := &Bucket{
- bucket: (*bucket)(unsafe.Pointer(&data[0])),
- name: name,
+ bucket: (*bucket)(unsafe.Pointer(&data[0])),
+ name: name,
transaction: t,
}
t.buckets[name] = b
@@ -76,85 +71,39 @@ func (t *Transaction) bucket(name string) (*Bucket, error) {
}
// Cursor creates a cursor associated with a given bucket.
-func (t *Transaction) Cursor(b *Bucket) (*Cursor, error) {
- if b == nil {
- return nil, &Error{"bucket required", nil}
- } else
-
- // Create a new cursor and associate it with the transaction and bucket.
- c := &Cursor{
- transaction: t,
- bucket: b,
- }
-
- // Set the first page if available.
- if b.root != p_invalid {
- p := t.db.page(t.db.data, int(b.root))
- c.top = 0
- c.pages = append(c.pages, p)
+func (t *Transaction) Cursor(name string) (*Cursor, error) {
+ b, err := t.Bucket(name)
+ if err != nil {
+ return nil, err
}
-
- return nil, nil
+ return b.Cursor()
}
-// Get retrieves the value for a key in a given bucket.
+// Get retrieves the value for a key in a named bucket.
func (t *Transaction) Get(name string, key []byte) ([]byte, error) {
- c, err := t.Cursor(name)
+ b, err := t.Bucket(name)
if err != nil {
return nil, err
}
- return c.Get(key)
-}
-
-func (t *Transaction) page(id int) (*page, error) {
- return t.db.page(id)
+ return b.Get(key)
}
// Stat returns information about a bucket's internal structure.
-func (t *Transaction) Stat(name string) *stat {
+func (t *Transaction) Stat(name string) *Stat {
// TODO
return nil
}
-// //
-// //
-// //
-// //
-// //
-// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ CONVERTED ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
-// //
-// //
-// //
-// //
-// //
-
-// Return the data associated with a given node.
-// @param[in] txn The transaction for this operation.
-// @param[in] leaf The node being read.
-// @param[out] data Updated to point to the node's data.
-// @return 0 on success, non-zero on failure.
-func (t *Transaction) readNode(leaf *node, data []byte) error {
- /*
- MDB_page *omp; // overflow page
- pgno_t pgno;
- int rc;
-
- if (!F_ISSET(leaf->mn_flags, F_BIGDATA)) {
- data->mv_size = NODEDSZ(leaf);
- data->mv_data = NODEDATA(leaf);
- return MDB_SUCCESS;
+// page returns a reference to the page with a given id.
+// If page has been written to then a temporary bufferred page is returned.
+func (t *Transaction) page(id pgid) *page {
+ // Check the dirty pages first.
+ if t.pages != nil {
+ if p, ok := t.pages[id]; ok {
+ return p
}
+ }
- // Read overflow data.
- data->mv_size = NODEDSZ(leaf);
- memcpy(&pgno, NODEDATA(leaf), sizeof(pgno));
- if ((rc = mdb_page_get(txn, pgno, &omp, NULL)) != 0) {
- DPRINTF(("read overflow page %"Z"u failed", pgno));
- return rc;
- }
- data->mv_data = METADATA(omp);
-
- return MDB_SUCCESS;
- */
- return nil
+ // Otherwise return directly from the mmap.
+ return t.db.page(id)
}