lbcd/ldb/tx.go
Dale Rahn 96f7305c29 One DB instad of many.
improved error handling

Fix testing, no point in running tests multiple times

Fix error when no blocks in database, reopen would misreport NewstSha() return
2013-09-10 10:05:26 -04:00

170 lines
4 KiB
Go

// Copyright (c) 2013 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package ldb
import (
"bytes"
"encoding/binary"
"fmt"
//"github.com/conformal/btcdb"
"github.com/conformal/btcwire"
)
type txUpdateObj struct {
txSha *btcwire.ShaHash
blkHeight int64
txoff int
txlen int
spentData []byte
delete bool
}
// InsertTx inserts a tx hash and its associated data into the database.
func (db *LevelDb) InsertTx(txsha *btcwire.ShaHash, height int64, txoff int, txlen int, spentbuf []byte) (err error) {
db.dbLock.Lock()
defer db.dbLock.Unlock()
return db.insertTx(txsha, height, txoff, txlen, spentbuf)
}
// insertTx inserts a tx hash and its associated data into the database.
// Must be called with db lock held.
func (db *LevelDb) insertTx(txSha *btcwire.ShaHash, height int64, txoff int, txlen int, spentbuf []byte) (err error) {
var txU txUpdateObj
txU.txSha = txSha
txU.blkHeight = height
txU.txoff = txoff
txU.txlen = txlen
txU.spentData = spentbuf
db.txUpdateMap[*txSha] = &txU
return nil
}
// formatTx generates the value buffer for the Tx db.
func (db *LevelDb) formatTx(txu *txUpdateObj) ([]byte, error) {
blkHeight := txu.blkHeight
txoff := txu.txoff
txlen := txu.txlen
spentbuf := txu.spentData
txOff := int32(txoff)
txLen := int32(txlen)
var txW bytes.Buffer
err := binary.Write(&txW, binary.LittleEndian, blkHeight)
if err != nil {
err = fmt.Errorf("Write fail")
return nil, err
}
err = binary.Write(&txW, binary.LittleEndian, txOff)
if err != nil {
err = fmt.Errorf("Write fail")
return nil, err
}
err = binary.Write(&txW, binary.LittleEndian, txLen)
if err != nil {
err = fmt.Errorf("Write fail")
return nil, err
}
err = binary.Write(&txW, binary.LittleEndian, spentbuf)
if err != nil {
err = fmt.Errorf("Write fail")
return nil, err
}
return txW.Bytes(), nil
}
func (db *LevelDb) getTxData(txsha *btcwire.ShaHash) (rblkHeight int64,
rtxOff int, rtxLen int, rspentBuf []byte, err error) {
var buf []byte
key := shaTxToKey(txsha)
buf, err = db.lDb.Get(key, db.ro)
if err != nil {
return
}
var blkHeight int64
var txOff, txLen int32
dr := bytes.NewBuffer(buf)
err = binary.Read(dr, binary.LittleEndian, &blkHeight)
if err != nil {
err = fmt.Errorf("Db Corrupt 1")
return
}
err = binary.Read(dr, binary.LittleEndian, &txOff)
if err != nil {
err = fmt.Errorf("Db Corrupt 2")
return
}
err = binary.Read(dr, binary.LittleEndian, &txLen)
if err != nil {
err = fmt.Errorf("Db Corrupt 3")
return
}
// remainder of buffer is spentbuf
spentBuf := make([]byte, dr.Len())
err = binary.Read(dr, binary.LittleEndian, spentBuf)
if err != nil {
err = fmt.Errorf("Db Corrupt 4")
return
}
return blkHeight, int(txOff), int(txLen), spentBuf, nil
}
// ExistsTxSha returns if the given tx sha exists in the database
func (db *LevelDb) ExistsTxSha(txsha *btcwire.ShaHash) (exists bool) {
db.dbLock.Lock()
defer db.dbLock.Unlock()
return db.existsTxSha(txsha)
}
// existsTxSha returns if the given tx sha exists in the database.o
// Must be called with the db lock held.
func (db *LevelDb) existsTxSha(txSha *btcwire.ShaHash) (exists bool) {
_, _, _, _, err := db.getTxData(txSha)
if err == nil {
return true
}
// BUG(drahn) If there was an error beside non-existant deal with it.
return false
}
// FetchLocationBySha looks up the Tx sha information by name.
func (db *LevelDb) FetchLocationBySha(txsha *btcwire.ShaHash) (blockidx int64, txoff int, txlen int, err error) {
db.dbLock.Lock()
defer db.dbLock.Unlock()
err = fmt.Errorf("obsolete function")
return
}
// FetchTxUsedBySha returns the used/spent buffer for a given transaction.
func (db *LevelDb) FetchTxUsedBySha(txSha *btcwire.ShaHash) (spentbuf []byte, err error) {
db.dbLock.Lock()
defer db.dbLock.Unlock()
_, _, _, spentbuf, err = db.getTxData(txSha)
if err != nil {
return
}
return // spentbuf has the value already
}
func (db *LevelDb) fetchLocationUsedBySha(txsha *btcwire.ShaHash) error {
// delete me
return fmt.Errorf("Deleted function")
}