github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/storage/localstore.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:45</date>
    10  //</624450120179519488>
    11  
    12  
    13  package storage
    14  
    15  import (
    16  	"context"
    17  	"path/filepath"
    18  	"sync"
    19  
    20  	"github.com/ethereum/go-ethereum/metrics"
    21  	"github.com/ethereum/go-ethereum/swarm/log"
    22  	"github.com/ethereum/go-ethereum/swarm/storage/mock"
    23  )
    24  
    25  type LocalStoreParams struct {
    26  	*StoreParams
    27  	ChunkDbPath string
    28  	Validators  []ChunkValidator `toml:"-"`
    29  }
    30  
    31  func NewDefaultLocalStoreParams() *LocalStoreParams {
    32  	return &LocalStoreParams{
    33  		StoreParams: NewDefaultStoreParams(),
    34  	}
    35  }
    36  
    37  //这只能在所有配置选项(文件、命令行、env vars)之后最终设置。
    38  //已经过评估
    39  func (p *LocalStoreParams) Init(path string) {
    40  	if p.ChunkDbPath == "" {
    41  		p.ChunkDbPath = filepath.Join(path, "chunks")
    42  	}
    43  }
    44  
    45  //localstore是InMemory数据库与磁盘持久化数据库的组合
    46  //使用任意2个chunkstore实现带有回退(缓存)逻辑的get/put
    47  type LocalStore struct {
    48  	Validators []ChunkValidator
    49  	memStore   *MemStore
    50  	DbStore    *LDBStore
    51  	mu         sync.Mutex
    52  }
    53  
    54  //此构造函数使用memstore和dbstore作为组件
    55  func NewLocalStore(params *LocalStoreParams, mockStore *mock.NodeStore) (*LocalStore, error) {
    56  	ldbparams := NewLDBStoreParams(params.StoreParams, params.ChunkDbPath)
    57  	dbStore, err := NewMockDbStore(ldbparams, mockStore)
    58  	if err != nil {
    59  		return nil, err
    60  	}
    61  	return &LocalStore{
    62  		memStore:   NewMemStore(params.StoreParams, dbStore),
    63  		DbStore:    dbStore,
    64  		Validators: params.Validators,
    65  	}, nil
    66  }
    67  
    68  func NewTestLocalStoreForAddr(params *LocalStoreParams) (*LocalStore, error) {
    69  	ldbparams := NewLDBStoreParams(params.StoreParams, params.ChunkDbPath)
    70  	dbStore, err := NewLDBStore(ldbparams)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  	localStore := &LocalStore{
    75  		memStore:   NewMemStore(params.StoreParams, dbStore),
    76  		DbStore:    dbStore,
    77  		Validators: params.Validators,
    78  	}
    79  	return localStore, nil
    80  }
    81  
    82  //如果块通过任何本地存储验证程序,则isvalid返回true。
    83  //如果localstore没有验证器,isvalid也返回true。
    84  func (ls *LocalStore) isValid(chunk Chunk) bool {
    85  //默认情况下,块是有效的。如果我们有0个验证器,那么所有的块都是有效的。
    86  	valid := true
    87  
    88  //validators包含每个块类型一个validator的列表。
    89  //如果一个验证器成功,那么块是有效的
    90  	for _, v := range ls.Validators {
    91  		if valid = v.Validate(chunk); valid {
    92  			break
    93  		}
    94  	}
    95  	return valid
    96  }
    97  
    98  //Put负责验证和存储块
    99  //通过使用配置的chunkvalidator、memstore和ldbstore。
   100  //如果区块无效,则其getErrored函数将
   101  //返回errchunkinvalid。
   102  //此方法将检查块是否已在memstore中
   103  //如果是的话,它会退回的。如果出现错误
   104  //memstore.get,将通过调用getErrored返回
   105  //在块上。
   106  //此方法负责关闭chunk.reqc通道
   107  //当块存储在memstore中时。
   108  //在ldbstore.put之后,确保memstore
   109  //包含具有相同数据但没有reqc通道的块。
   110  func (ls *LocalStore) Put(ctx context.Context, chunk Chunk) error {
   111  	if !ls.isValid(chunk) {
   112  		return ErrChunkInvalid
   113  	}
   114  
   115  	log.Trace("localstore.put", "key", chunk.Address())
   116  	ls.mu.Lock()
   117  	defer ls.mu.Unlock()
   118  
   119  	_, err := ls.memStore.Get(ctx, chunk.Address())
   120  	if err == nil {
   121  		return nil
   122  	}
   123  	if err != nil && err != ErrChunkNotFound {
   124  		return err
   125  	}
   126  	ls.memStore.Put(ctx, chunk)
   127  	err = ls.DbStore.Put(ctx, chunk)
   128  	return err
   129  }
   130  
   131  //get(chunk*chunk)在本地商店中查找一个chunk
   132  //在获取块之前,此方法正在阻塞
   133  //因此,如果
   134  //chunkstore是远程的,可以有很长的延迟
   135  func (ls *LocalStore) Get(ctx context.Context, addr Address) (chunk Chunk, err error) {
   136  	ls.mu.Lock()
   137  	defer ls.mu.Unlock()
   138  
   139  	return ls.get(ctx, addr)
   140  }
   141  
   142  func (ls *LocalStore) get(ctx context.Context, addr Address) (chunk Chunk, err error) {
   143  	chunk, err = ls.memStore.Get(ctx, addr)
   144  
   145  	if err != nil && err != ErrChunkNotFound {
   146  		metrics.GetOrRegisterCounter("localstore.get.error", nil).Inc(1)
   147  		return nil, err
   148  	}
   149  
   150  	if err == nil {
   151  		metrics.GetOrRegisterCounter("localstore.get.cachehit", nil).Inc(1)
   152  		go ls.DbStore.MarkAccessed(addr)
   153  		return chunk, nil
   154  	}
   155  
   156  	metrics.GetOrRegisterCounter("localstore.get.cachemiss", nil).Inc(1)
   157  	chunk, err = ls.DbStore.Get(ctx, addr)
   158  	if err != nil {
   159  		metrics.GetOrRegisterCounter("localstore.get.error", nil).Inc(1)
   160  		return nil, err
   161  	}
   162  
   163  	ls.memStore.Put(ctx, chunk)
   164  	return chunk, nil
   165  }
   166  
   167  func (ls *LocalStore) FetchFunc(ctx context.Context, addr Address) func(context.Context) error {
   168  	ls.mu.Lock()
   169  	defer ls.mu.Unlock()
   170  
   171  	_, err := ls.get(ctx, addr)
   172  	if err == nil {
   173  		return nil
   174  	}
   175  	return func(context.Context) error {
   176  		return err
   177  	}
   178  }
   179  
   180  func (ls *LocalStore) BinIndex(po uint8) uint64 {
   181  	return ls.DbStore.BinIndex(po)
   182  }
   183  
   184  func (ls *LocalStore) Iterator(from uint64, to uint64, po uint8, f func(Address, uint64) bool) error {
   185  	return ls.DbStore.SyncIterator(from, to, po, f)
   186  }
   187  
   188  //关闭本地存储
   189  func (ls *LocalStore) Close() {
   190  	ls.DbStore.Close()
   191  }
   192  
   193  //迁移检查数据存储架构与运行时架构并运行
   194  //迁移如果不匹配
   195  func (ls *LocalStore) Migrate() error {
   196  	actualDbSchema, err := ls.DbStore.GetSchema()
   197  	if err != nil {
   198  		log.Error(err.Error())
   199  		return err
   200  	}
   201  
   202  	if actualDbSchema == CurrentDbSchema {
   203  		return nil
   204  	}
   205  
   206  	log.Debug("running migrations for", "schema", actualDbSchema, "runtime-schema", CurrentDbSchema)
   207  
   208  	if actualDbSchema == DbSchemaNone {
   209  		ls.migrateFromNoneToPurity()
   210  		actualDbSchema = DbSchemaPurity
   211  	}
   212  
   213  	if err := ls.DbStore.PutSchema(actualDbSchema); err != nil {
   214  		return err
   215  	}
   216  
   217  	if actualDbSchema == DbSchemaPurity {
   218  		if err := ls.migrateFromPurityToHalloween(); err != nil {
   219  			return err
   220  		}
   221  		actualDbSchema = DbSchemaHalloween
   222  	}
   223  
   224  	if err := ls.DbStore.PutSchema(actualDbSchema); err != nil {
   225  		return err
   226  	}
   227  	return nil
   228  }
   229  
   230  func (ls *LocalStore) migrateFromNoneToPurity() {
   231  //删除无效的块,即不通过的块
   232  //任何ls.validator
   233  	ls.DbStore.Cleanup(func(c *chunk) bool {
   234  		return !ls.isValid(c)
   235  	})
   236  }
   237  
   238  func (ls *LocalStore) migrateFromPurityToHalloween() error {
   239  	return ls.DbStore.CleanGCIndex()
   240  }
   241