Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions walletdb/hdb/db.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package hdb

import (
"errors"
"io"

"github.com/btcsuite/btcwallet/walletdb"
hamtcontainer "github.com/simplecoincom/go-ipld-adl-hamt-container"
)

const (
// metadataDbName is the name used for the metadata database.
metadataDbName = "metadata"
)

// db represents a collection of namespaces which are persisted and implements
// the database.DB interface. All database access is performed through
// transactions which are obtained through the specific Namespace.
type db struct {
closed bool // Is the database closed?
hdb *hamtcontainer.HAMTContainer
}

// Enforce db implements the database.DB interface.
var _ walletdb.DB = (*db)(nil)

// bucket is an internal type used to represent a collection of key/value pairs
// and implements the database.Bucket interface.
type bucket struct {
id [4]byte
}

// ReadBucket opens the root bucket for read only access. If the bucket
// described by the key does not exist, nil is returned.
func (b *bucket) ReadBucket(_ []byte) walletdb.ReadBucket {
return nil
}

// ForEachBucket will iterate through all top level buckets.
func (b *bucket) ForEachBucket(func(key []byte) error) error {
return nil
}

// Rollback closes the transaction, discarding changes (if any) if the
// database was modified by a write transaction.
func (b *bucket) Rollback() error {
return nil
}

// ReadWriteBucket opens the root bucket for read/write access. If the
// bucket described by the key does not exist, nil is returned.
func (b *bucket) ReadWriteBucket(_ []byte) walletdb.ReadWriteBucket {
return nil
}

// CreateTopLevelBucket creates the top level bucket for a key if it
// does not exist. The newly-created bucket it returned.
func (b *bucket) CreateTopLevelBucket(_ []byte) (walletdb.ReadWriteBucket, error) {
return nil, nil
}

// DeleteTopLevelBucket deletes the top level bucket for a key. This
// errors if the bucket can not be found or the key keys a single value
// instead of a bucket.
func (b *bucket) DeleteTopLevelBucket(_ []byte) error {
return nil
}

// Commit commits all changes that have been on the transaction's root
// buckets and all of their sub-buckets to persistent storage.
func (b *bucket) Commit() error {
return nil
}

// OnCommit takes a function closure that will be executed when the
// transaction successfully gets committed.
func (b *bucket) OnCommit(func()) {

}

// CreateBucket creates and returns a new nested bucket with the given key.
//
// Returns the following errors as required by the interface contract:
// - ErrBucketExists if the bucket already exists
// - ErrBucketNameRequired if the key is empty
// - ErrIncompatibleValue if the key is otherwise invalid for the particular
// implementation
// - ErrTxNotWritable if attempted against a read-only transaction
// - ErrTxClosed if the transaction has already been closed
//
// This function is part of the database.Bucket interface implementation.
func (b *bucket) CreateBucket(_ []byte) (walletdb.ReadWriteBucket, error) {
return nil, nil
}

// BeginReadTx starts a read-only transaction. Multiple read-only transactions
// can be started simultaneously while only a single read-write transaction can
// be started at a time.
//
// NOTE: The transaction must be closed by calling Rollbackon it when it is no
// longer needed. Failure to do so will result in unclaimed memory.
//
// This function is part of the walletdb.DB interface implementation.
func (db *db) BeginReadTx() (walletdb.ReadTx, error) {
return &bucket{id: [4]byte{}}, nil
}

// BeginReadTx starts a read-write transaction. Multiple read-only transactions
// can be started simultaneously while only a single read-write transaction can
// be started at a time. The call will block when a read-write transaction is
// already open.
//
// NOTE: The transaction must be closed by calling Rollback or Commit on it when
// it is no longer needed. Failure to do so will result in unclaimed memory.
//
// This function is part of the walletdb.DB interface implementation.
func (db *db) BeginReadWriteTx() (walletdb.ReadWriteTx, error) {
return &bucket{id: [4]byte{}}, nil
}

// TODO(eduardonunesp): implement this
func (db *db) Copy(_ io.Writer) error {
return errors.New("Not implemented yet")
}

// Batch is required by the BatchDB interface
func (db *db) Batch(fn func(tx walletdb.ReadWriteTx) error) error {
return walletdb.Update(db, fn)
}

// Close cleanly shuts down the database and syncs all data. It will block
// until all database transactions have been finalized (rolled back or
// committed).
//
// This function is part of the database.DB interface implementation.
func (db *db) Close() error {
if db.closed {
return walletdb.ErrDbNotOpen
}
db.closed = true
return nil
}

// openDB opens the database at the provided path. walletdb.ErrDbDoesNotExist
// is returned if the database doesn't exist and the create flag is not set.
func openDB(ipfsURL string) (walletdb.DB, error) {
_ = ipfsURL

hdb, err := hamtcontainer.NewHAMTBuilder().Build()
if err != nil {
return nil, err
}

pdb := &db{hdb: hdb}

return pdb, nil
}
68 changes: 68 additions & 0 deletions walletdb/hdb/driver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) 2014 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package hdb

import (
"fmt"

"github.com/btcsuite/btcwallet/walletdb"
)

const (
dbType = "hdb"
)

// parseArgs parses the arguments from the walletdb Open/Create methods.
func parseArgs(funcName string, args ...interface{}) (string, error) {
if len(args) < 1 {
return "", fmt.Errorf("invalid arguments to %s.%s -- "+
"expected ipfs url",
dbType, funcName)
}

ipfsURL, ok := args[0].(string)
if !ok {
return "", fmt.Errorf("first argument to %s.%s is "+
"invalid -- expected ipfs url", dbType,
funcName)
}

return ipfsURL, nil
}

// openDBDriver is the callback provided during driver registration that opens
// an existing database for use.
func openDBDriver(args ...interface{}) (walletdb.DB, error) {
dbPath, err := parseArgs("Open", args...)
if err != nil {
return nil, err
}

return openDB(dbPath)
}

// createDBDriver is the callback provided during driver registration that
// creates, initializes, and opens a database for use.
func createDBDriver(args ...interface{}) (walletdb.DB, error) {
dbPath, err := parseArgs("Create", args...)
if err != nil {
return nil, err
}

return openDB(dbPath)
}

func init() {
// Register the driver.
driver := walletdb.Driver{
DbType: dbType,
Create: createDBDriver,
Open: openDBDriver,
}
if err := walletdb.RegisterDriver(driver); err != nil {
panic(fmt.Sprintf("Failed to regiser database driver '%s': %v",
dbType, err))
}
}
4 changes: 4 additions & 0 deletions walletdb/hdb/driver_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package hdb_test

// dbType is the database type name for this driver.
const dbType = "hdb"
36 changes: 36 additions & 0 deletions walletdb/hdb/interface_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) 2014 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

// This file intended to be copied into each backend driver directory. Each
// driver should have their own driver_test.go file which creates a database and
// invokes the testInterface function in this file to ensure the driver properly
// implements the interface. See the bdb backend driver for a working example.
//
// NOTE: When copying this file into the backend driver folder, the package name
// will need to be changed accordingly.

package hdb_test

import (
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/btcsuite/btcwallet/walletdb/walletdbtest"
)

// TestInterface performs all interfaces tests for this database driver.
func TestInterface(t *testing.T) {
tempDir, err := ioutil.TempDir("", "interfacetest")
if err != nil {
t.Errorf("unable to create temp dir: %v", err)
return
}
defer os.Remove(tempDir)

dbPath := filepath.Join(tempDir, "db")
defer os.RemoveAll(dbPath)
walletdbtest.TestInterface(t, dbType, dbPath)
}