Go-ethereum 源碼解析之 go-ethereum/ethdb/database.go
Source code
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
Appendix A. 總體批注
實現(xiàn)了底層數(shù)據(jù)庫 LevelDB 的抽象層 LDBDatabase,用于生產(chǎn)環(huán)境。
ethdb.LDBDatabase 實現(xiàn)了接口 ethdb.Database完箩,并且將實際的操作轉(zhuǎn)發(fā)給 LevelDB 的接口泵喘。同時,基于 metrics.Meter 測試各操作的性能秆乳。
ethdb.ldbBatch 在 ethdb.LDBDatabase 的基礎(chǔ)上提供了批處理能力懦鼠。
暫時不深入與性能相關(guān)的實現(xiàn) metrics.Meter钻哩。
Appendix B. 詳細批注
1. const
- writePauseWarningThrottler = 1 * time.Minute: ??? 性能相關(guān)指標
2. var
- var OpenFileLimit = 64: ??? LevelDB 一次能打開的文件數(shù)量上限?
3. type LDBDatabase struct
數(shù)據(jù)結(jié)構(gòu) LDBDatabase 實現(xiàn)了接口 ethdb.Database肛冶,并且將實際的操作轉(zhuǎn)發(fā)給 LevelDB 的接口街氢。同時,基于 metrics.Meter 測試各操作的性能睦袖。
fn string: 文件名珊肃。??? 干什么的文件名呢?
db *leveldb.DB: LevelDB 實例
compTimeMeter metrics.Meter // Meter for measuring the total time spent in database compaction
compReadMeter metrics.Meter // Meter for measuring the data read during compaction
compWriteMeter metrics.Meter // Meter for measuring the data written during compaction
writeDelayNMeter metrics.Meter // Meter for measuring the write delay number due to database compaction
writeDelayMeter metrics.Meter // Meter for measuring the write delay duration due to database compaction
diskReadMeter metrics.Meter // Meter for measuring the effective amount of data read
diskWriteMeter metrics.Meter // Meter for measuring the effective amount of data written
quitLock sync.Mutex // Mutex protecting the quit channel access
quitChan chan chan error // Quit channel to stop the metrics collection before closing the database
log log.Logger // Contextual logger tracking the database path
3.1 func NewLDBDatabase(file string, cache int, handles int) (*LDBDatabase, error)
構(gòu)造函數(shù) NewLDBDatabase() 創(chuàng)建 LDBDatabase 的一個實例扣泊,該實例是 LevelDB 的包裝器近范。
參數(shù):
- file string: 文件名
- cache int: ??? 緩存?
- handles int: ??? 處理器延蟹?
返回值:
- LDBDatabase 實例
- 出錯返回錯誤消息 error评矩,否則返回 nil
主要實現(xiàn):
-
構(gòu)建日志器 logger
- logger := log.New("database", file)
調(diào)整 cache,確保其最小值為 16
調(diào)整 handles阱飘,確保其最小值為 16
輸出日志信息:logger.Info("Allocated cache and file handles", "cache", cache, "handles", handles)
-
打開 LevelDB斥杜,并從可能的錯誤恢復(fù)
- db, err := leveldb.OpenFile(file, ...)
- corrupted := err.(*errors.ErrCorrupted)
- db, err = leveldb.RecoverFile(file, nil)
-
如果 err 不為 nil,則直接退出
- return nil, err
-
構(gòu)建 LDBDatabase 的實例并返回
- return &LDBDatabase{fn: file, db: db, log: logger}, nil
注意沥匈,這里并沒有初始化任何性能計時器蔗喂。
3.2 func (db *LDBDatabase) Path() string
方法 Path() 返回數(shù)據(jù)庫目錄的路徑。
3.3 func (db *LDBDatabase) Put(key []byte, value []byte) error
方法 Put() 實現(xiàn)了接口 ethdb.Putter 和接口 ethdb.Database高帖,將 key & value 寫入數(shù)據(jù)庫缰儿。
參數(shù):
- key []byte: key
- value []byte: value
返回值:
- 出錯返回錯誤消息 error,否則返回 nil
主要實現(xiàn):
- 轉(zhuǎn)發(fā)給 LevelDB 的方法 Put()
- return db.db.Put(key, value, nil)
3.4 func (db *LDBDatabase) Has(key []byte) (bool, error)
方法 Has() 實現(xiàn)了接口 ethdb.Database散址,查詢給定的 key 是否存在于數(shù)據(jù)庫乖阵。
參數(shù):
- key []byte: key
返回值:
- 存在返回 true,否則返回 false
- 出錯返回錯誤消息 error预麸,否則返回 nil
主要實現(xiàn):
- 轉(zhuǎn)發(fā)給 LevelDB 的方法 Has()
- return db.db.Has(key, nil)
3.5 func (db *LDBDatabase) Get(key []byte) ([]byte, error)
方法 Get() 實現(xiàn)了接口 ethdb.Database瞪浸,從數(shù)據(jù)庫中獲取給定 key 對應(yīng)的 value蕾殴。
參數(shù):
- key []byte: key
返回值:
- 存在返回 key 對應(yīng)的 value
- 出錯返回錯誤消息 error闹丐,否則返回 nil
主要實現(xiàn):
- 轉(zhuǎn)發(fā)給 LevelDB 的方法 Get()
- dat, err := db.db.Get(key, nil)
3.6 func (db *LDBDatabase) Delete(key []byte) error
方法 Delete() 實現(xiàn)了接口 ethdb.Database,從數(shù)據(jù)庫中刪除指定的 key川蒙。
參數(shù):
- key []byte: key
返回值:
- 出錯返回錯誤消息 error贡翘,否則返回 nil
主要實現(xiàn):
- 轉(zhuǎn)發(fā)給 LevelDB 的方法 Delete()
- return db.db.Delete(key, nil)
3.7 func (db *LDBDatabase) NewIterator() iterator.Iterator
方法 NewIterator() 返回 LevelDB 的迭代器 iterator.Iterator蹈矮。
返回值:
- LevelDB 的迭代器 iterator.Iterator
主要實現(xiàn):
- return db.db.NewIterator(nil, nil)
3.8 func (db *LDBDatabase) NewIteratorWithPrefix(prefix []byte) iterator.Iterator
方法 NewIteratorWithPrefix() 返回 LevelDB 的迭代器 iterator.Iterator,這個迭代器指向具有指定前綴的數(shù)據(jù)庫子集床估。
參數(shù):
- prefix []byte: 前綴
返回值:
- LevelDB 的迭代器 iterator.Iterator
主要實現(xiàn):
- return db.db.NewIterator(util.BytesPrefix(prefix), nil)
3.9 func (db *LDBDatabase) Close()
方法 Close() 實現(xiàn)了接口 ethdb.Database含滴。
主要實現(xiàn):
- ??? 停止性能指標器
- 將實際的關(guān)閉操作轉(zhuǎn)發(fā)給 LevelDB 的方法 Close()
- err := db.db.Close()
- 如果 err == nil
- db.log.Info("Database closed")
- 否則
- db.log.Error("Failed to close database", "err", err)
3.10 func (db *LDBDatabase) LDB() *leveldb.DB
方法 LDB() 返回 LDBDatabase 中的底層 LevelDB 數(shù)據(jù)庫。
返回值:
- LDBDatabase 中的底層 LevelDB 數(shù)據(jù)庫丐巫。
主要實現(xiàn):
- return db.db
3.11 func (db *LDBDatabase) Meter(prefix string)
性能指標相關(guān)內(nèi)容谈况,暫時不關(guān)注勺美。
3.12 func (db *LDBDatabase) meter(refresh time.Duration)
性能指標相關(guān)內(nèi)容,暫時不關(guān)注碑韵。
3.13 func (db *LDBDatabase) NewBatch() Batch
方法 NewBatch() 返回批處理器赡茸。
返回值:
- 批處理器 ldbBatch
主要實現(xiàn):
- return &ldbBatch{db: db.db, b: new(leveldb.Batch)}
4. type ldbBatch struct
數(shù)據(jù)結(jié)構(gòu) ldbBatch 在 LevelDB 的基礎(chǔ)上提供批處理能力。
- db *leveldb.DB: 底層的 LevelDB
- b *leveldb.Batch: LevelDB 的批處理器
- size int: 字節(jié)數(shù)
4.1 func (b *ldbBatch) Put(key, value []byte) error
方法 Put() 實現(xiàn)了接口 ethdb.Putter 和接口 ethdb.Batch祝闻,將 key & value 寫入數(shù)據(jù)庫占卧。
參數(shù):
- key []byte: key
- value []byte: value
返回值:
- 出錯返回錯誤消息 error,否則返回 nil
主要實現(xiàn):
- 轉(zhuǎn)發(fā)給 leveldb.Batch 的方法 Put()
- b.b.Put(key, value)
- 更新字節(jié)數(shù)
- b.size += len(value)
4.2 func (b *ldbBatch) Delete(key []byte) error
方法 Delete() 實現(xiàn)了接口 ethdb.Deleter 和接口 ethdb.Batch联喘,從數(shù)據(jù)庫中刪除指定的 key华蜒。
參數(shù):
- key []byte: key
返回值:
- 出錯返回錯誤消息 error,否則返回 nil
主要實現(xiàn):
- 轉(zhuǎn)發(fā)給 leveldb.Batch 的方法 Delete()
- b.b.Delete(key)
- 更新字節(jié)數(shù)
- b.size += 1
4.3 func (b *ldbBatch) Write() error
方法 Write() 實現(xiàn)了接口 ethdb.Batch豁遭,將批量數(shù)據(jù)一次性寫入數(shù)據(jù)庫叭喜。
返回值:
- 出錯返回錯誤消息 error,否則返回 nil
主要實現(xiàn):
- return b.db.Write(b.b, nil)
4.4 func (b *ldbBatch) ValueSize() int
方法 ValueSize() 實現(xiàn)了接口 ethdb.Batch蓖谢,返回批量字節(jié)數(shù)捂蕴。
返回值:
- 批量字節(jié)數(shù)
主要實現(xiàn):
- return b.size
4.5 func (b *ldbBatch) Reset()
方法 Reset() 實現(xiàn)了接口 ethdb.Batch,重置數(shù)據(jù)庫闪幽。
主要實現(xiàn):
- 轉(zhuǎn)發(fā)給 leveldb.Batch 的方法 Reset()
- b.b.Reset()
- 更新字節(jié)數(shù)
- b.size = 0
5. type table struct
數(shù)據(jù)結(jié)構(gòu) table 封裝了數(shù)據(jù)庫 Database啥辨,描述 Database 中的 key 具有相同的前綴 prefix。
- db Database: 數(shù)據(jù)庫
- prefix string: 前綴
5.1 func NewTable(db Database, prefix string) Database
構(gòu)造函數(shù) NewTable() 創(chuàng)建數(shù)據(jù)庫盯腌,同時數(shù)據(jù)庫中的 key 具有相同的前綴 prefix溉知。
參數(shù):
- db Database: 數(shù)據(jù)庫
- prefix string: 前綴
返回值:
- 數(shù)據(jù)庫
主要實現(xiàn):
- return &table{db: db, prefix: prefix,}
5.2 func (dt *table) Put(key []byte, value []byte) error
方法 Put() 實現(xiàn)了接口 ethdb.Putter 和接口 ethdb.Database。
參數(shù):
- key []byte: key
- value []byte: value
返回值:
- 出錯返回錯誤消息 error腕够,否則返回 nil
主要實現(xiàn):
- 給 key 加上前綴 prefix着倾,同時轉(zhuǎn)發(fā)給 Database 的方法 Put()
- dt.db.Put(append([]byte(dt.prefix), key...), value)
5.3 func (dt *table) Has(key []byte) (bool, error)
方法 Has() 實現(xiàn)了接口 ethdb.Database。
參數(shù):
- key []byte: key
返回值:
- 存在返回 true燕少,否則返回 false
- 出錯返回錯誤消息 error,否則返回 nil
主要實現(xiàn):
- 給 key 加上前綴 prefix蒿囤,同時轉(zhuǎn)發(fā)給 Database 的方法 Has()
- dt.db.Has(append([]byte(dt.prefix), key...))
5.4 func (dt *table) Get(key []byte) ([]byte, error)
方法 Get() 實現(xiàn)了接口 ethdb.Database客们。
參數(shù):
- key []byte: key
返回值:
- 存在返回 key 對應(yīng)的 value
- 出錯返回錯誤消息 error,否則返回 nil
主要實現(xiàn):
- 給 key 加上前綴 prefix材诽,同時轉(zhuǎn)發(fā)給 Database 的方法 Get()
- dt.db.Get(append([]byte(dt.prefix), key...))
5.5 func (dt *table) Delete(key []byte) error
方法 Delete() 實現(xiàn)了接口 ethdb.Deleter 和接口 ethdb.Database底挫。
參數(shù):
- key []byte: key
返回值:
- 出錯返回錯誤消息 error,否則返回 nil
主要實現(xiàn):
- 給 key 加上前綴 prefix脸侥,同時轉(zhuǎn)發(fā)給 Database 的方法 Delete()
- dt.db.Delete(append([]byte(dt.prefix), key...))
5.6 func (dt *table) Close()
方法 Close() 不執(zhí)行任何操作建邓。注意,這里并不會關(guān)閉底層數(shù)據(jù)庫睁枕。
5.7 func (dt *table) NewBatch() Batch
方法 NewBatch() 返回具有批處理能力的 ethdb.table官边。
返回值:
- 具有批處理能力的 ethdb.tableBatch
主要實現(xiàn):
- return &tableBatch{dt.db.NewBatch(), dt.prefix}
6. type tableBatch struct
數(shù)據(jù)結(jié)構(gòu) tableBatch 封裝了數(shù)據(jù)庫 Database沸手,描述 Database 中的 key 具有相同的前綴 prefix。同時注簿,提供批處理能力契吉。
- batch Batch: 批處理
- prefix string: 前綴
6.1 func NewTableBatch(db Database, prefix string) Batch
構(gòu)造函數(shù) NewTableBatch() 創(chuàng)建具有批處理能力的數(shù)據(jù)庫,同時數(shù)據(jù)庫中的 key 具有相同的前綴 prefix诡渴。
參數(shù):
- db Database: 數(shù)據(jù)庫
- prefix string: 前綴
返回值:
- 具有批處理能力數(shù)據(jù)庫
主要實現(xiàn):
- return &tableBatch{db.NewBatch(), prefix}
6.2 func (tb *tableBatch) Put(key, value []byte) error
方法 Put() 實現(xiàn)了接口 ethdb.Putter 和接口 ethdb.Batch捐晶,將 key & value 插入數(shù)據(jù)庫。
參數(shù):
- key []byte: key
- value []byte: value
返回值:
- 出錯返回錯誤消息 error妄辩,否則返回 nil
主要實現(xiàn):
- 給 key 加上前綴 prefix惑灵,同時轉(zhuǎn)發(fā)給 ethdb.Batch 的方法 Put()
- return tb.batch.Put(append([]byte(tb.prefix), key...), value)
6.3 func (tb *tableBatch) Delete(key []byte) error
方法 Delete() 實現(xiàn)了接口 ethdb.Deleter 和接口 ethdb.Batch,從數(shù)據(jù)庫中刪除給定的 key眼耀。
參數(shù):
- key []byte: key
返回值:
- 出錯返回錯誤消息 error英支,否則返回 nil
主要實現(xiàn):
- 給 key 加上前綴 prefix,同時轉(zhuǎn)發(fā)給 ethdb.Batch 的方法 Delete()
- return tb.batch.Delete(append([]byte(tb.prefix), key...))
6.4 func (tb *tableBatch) Write() error
方法 Write() 實現(xiàn)了接口 ethdb.Batch畔塔,將批處理數(shù)據(jù)一次性寫入數(shù)據(jù)庫潭辈。
返回值:
- 出錯返回錯誤消息 error,否則返回 nil
主要實現(xiàn):
- 轉(zhuǎn)發(fā)給 ethdb.Batch 的方法 Write()
- return tb.batch.Write()
6.5 func (tb *tableBatch) ValueSize() int
方法 ValueSize() 實現(xiàn)了接口 ethdb.Batch澈吨,返回批處理數(shù)據(jù)的字節(jié)數(shù)把敢。
返回值:
- 批處理數(shù)據(jù)字節(jié)數(shù)
主要實現(xiàn):
- 轉(zhuǎn)發(fā)給 ethdb.Batch 的方法 ValueSize()
- return tb.batch.ValueSize()
6.6 func (tb *tableBatch) Reset()
方法 Reset() 實現(xiàn)了接口 ethdb.Batch谅辣,清空批處理數(shù)據(jù)修赞。
主要實現(xiàn):
- 轉(zhuǎn)發(fā)給 ethdb.Batch 的方法 Reset()
- tb.batch.Reset()
Reference
Contributor
- Windstamp, https://github.com/windstamp