Do a little addrindex database cleanup.

- Use explicit index values for byte slices
- Fix a bug in FetchTxsForAddr that allocated an extra 10 bytes
  for each address index
- Add missing iterator release in error path
- Check for iterator errors.
This commit is contained in:
David Hill 2015-03-14 22:09:51 -04:00
parent 369b352452
commit ccc3a9b979
2 changed files with 19 additions and 11 deletions

View file

@ -15,6 +15,7 @@ import (
func TestAddrIndexKeySerialization(t *testing.T) { func TestAddrIndexKeySerialization(t *testing.T) {
var hash160Bytes [ripemd160.Size]byte var hash160Bytes [ripemd160.Size]byte
var packedIndex [12]byte
fakeHash160 := btcutil.Hash160([]byte("testing")) fakeHash160 := btcutil.Hash160([]byte("testing"))
copy(fakeHash160, hash160Bytes[:]) copy(fakeHash160, hash160Bytes[:])
@ -27,7 +28,8 @@ func TestAddrIndexKeySerialization(t *testing.T) {
} }
serializedKey := addrIndexToKey(&fakeIndex) serializedKey := addrIndexToKey(&fakeIndex)
unpackedIndex := unpackTxIndex(serializedKey[22:]) copy(packedIndex[:], serializedKey[22:34])
unpackedIndex := unpackTxIndex(packedIndex)
if unpackedIndex.blkHeight != fakeIndex.blkHeight { if unpackedIndex.blkHeight != fakeIndex.blkHeight {
t.Errorf("Incorrect block height. Unpack addr index key"+ t.Errorf("Incorrect block height. Unpack addr index key"+

View file

@ -374,7 +374,7 @@ func (db *LevelDb) FetchTxBySha(txsha *wire.ShaHash) ([]*database.TxListReply, e
// addrIndexToKey serializes the passed txAddrIndex for storage within the DB. // addrIndexToKey serializes the passed txAddrIndex for storage within the DB.
func addrIndexToKey(index *txAddrIndex) []byte { func addrIndexToKey(index *txAddrIndex) []byte {
record := make([]byte, addrIndexKeyLength, addrIndexKeyLength) record := make([]byte, addrIndexKeyLength, addrIndexKeyLength)
copy(record[:2], addrIndexKeyPrefix) copy(record[0:2], addrIndexKeyPrefix)
copy(record[2:22], index.hash160[:]) copy(record[2:22], index.hash160[:])
// The index itself. // The index itself.
@ -386,7 +386,7 @@ func addrIndexToKey(index *txAddrIndex) []byte {
} }
// unpackTxIndex deserializes the raw bytes of a address tx index. // unpackTxIndex deserializes the raw bytes of a address tx index.
func unpackTxIndex(rawIndex []byte) *txAddrIndex { func unpackTxIndex(rawIndex [12]byte) *txAddrIndex {
return &txAddrIndex{ return &txAddrIndex{
blkHeight: int64(binary.LittleEndian.Uint32(rawIndex[0:4])), blkHeight: int64(binary.LittleEndian.Uint32(rawIndex[0:4])),
txoffset: int(binary.LittleEndian.Uint32(rawIndex[4:8])), txoffset: int(binary.LittleEndian.Uint32(rawIndex[4:8])),
@ -447,20 +447,19 @@ func (db *LevelDb) FetchTxsForAddr(addr btcutil.Address, skip int,
// Create the prefix for our search. // Create the prefix for our search.
addrPrefix := make([]byte, 22, 22) addrPrefix := make([]byte, 22, 22)
copy(addrPrefix[:2], addrIndexKeyPrefix) copy(addrPrefix[0:2], addrIndexKeyPrefix)
copy(addrPrefix[2:], addrKey) copy(addrPrefix[2:22], addrKey)
var replies []*database.TxListReply
iter := db.lDb.NewIterator(bytesPrefix(addrPrefix), nil) iter := db.lDb.NewIterator(bytesPrefix(addrPrefix), nil)
for skip != 0 && iter.Next() { for skip != 0 && iter.Next() {
skip-- skip--
} }
// Iterate through all address indexes that match the targeted prefix. // Iterate through all address indexes that match the targeted prefix.
var replies []*database.TxListReply
var rawIndex [12]byte
for iter.Next() && limit != 0 { for iter.Next() && limit != 0 {
rawIndex := make([]byte, 22, 22) copy(rawIndex[:], iter.Key()[22:34])
copy(rawIndex, iter.Key()[22:])
addrIndex := unpackTxIndex(rawIndex) addrIndex := unpackTxIndex(rawIndex)
tx, blkSha, blkHeight, _, err := db.fetchTxDataByLoc(addrIndex.blkHeight, tx, blkSha, blkHeight, _, err := db.fetchTxDataByLoc(addrIndex.blkHeight,
@ -478,6 +477,9 @@ func (db *LevelDb) FetchTxsForAddr(addr btcutil.Address, skip int,
limit-- limit--
} }
iter.Release() iter.Release()
if err := iter.Error(); err != nil {
return nil, err
}
return replies, nil return replies, nil
} }
@ -522,8 +524,8 @@ func (db *LevelDb) UpdateAddrIndexForBlock(blkSha *wire.ShaHash, blkHeight int64
// Update tip of addrindex. // Update tip of addrindex.
newIndexTip := make([]byte, 40, 40) newIndexTip := make([]byte, 40, 40)
copy(newIndexTip[:32], blkSha.Bytes()) copy(newIndexTip[0:32], blkSha.Bytes())
binary.LittleEndian.PutUint64(newIndexTip[32:], uint64(blkHeight)) binary.LittleEndian.PutUint64(newIndexTip[32:40], uint64(blkHeight))
batch.Put(addrIndexMetaDataKey, newIndexTip) batch.Put(addrIndexMetaDataKey, newIndexTip)
if err := db.lDb.Write(batch, db.wo); err != nil { if err := db.lDb.Write(batch, db.wo); err != nil {
@ -557,6 +559,7 @@ func (db *LevelDb) DeleteAddrIndex() error {
// Delete in chunks to potentially avoid very large batches. // Delete in chunks to potentially avoid very large batches.
if numInBatch >= batchDeleteThreshold { if numInBatch >= batchDeleteThreshold {
if err := db.lDb.Write(batch, db.wo); err != nil { if err := db.lDb.Write(batch, db.wo); err != nil {
iter.Release()
return err return err
} }
batch.Reset() batch.Reset()
@ -564,6 +567,9 @@ func (db *LevelDb) DeleteAddrIndex() error {
} }
} }
iter.Release() iter.Release()
if err := iter.Error(); err != nil {
return err
}
batch.Delete(addrIndexMetaDataKey) batch.Delete(addrIndexMetaDataKey)
if err := db.lDb.Write(batch, db.wo); err != nil { if err := db.lDb.Write(batch, db.wo); err != nil {