github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/storage/localstore.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //
    10  //
    11  //
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  
    25  package storage
    26  
    27  import (
    28  	"context"
    29  	"encoding/binary"
    30  	"fmt"
    31  	"path/filepath"
    32  	"sync"
    33  
    34  	"github.com/ethereum/go-ethereum/metrics"
    35  	"github.com/ethereum/go-ethereum/swarm/log"
    36  	"github.com/ethereum/go-ethereum/swarm/storage/mock"
    37  )
    38  
    39  type LocalStoreParams struct {
    40  	*StoreParams
    41  	ChunkDbPath string
    42  	Validators  []ChunkValidator `toml:"-"`
    43  }
    44  
    45  func NewDefaultLocalStoreParams() *LocalStoreParams {
    46  	return &LocalStoreParams{
    47  		StoreParams: NewDefaultStoreParams(),
    48  	}
    49  }
    50  
    51  //
    52  //
    53  func (p *LocalStoreParams) Init(path string) {
    54  	if p.ChunkDbPath == "" {
    55  		p.ChunkDbPath = filepath.Join(path, "chunks")
    56  	}
    57  }
    58  
    59  //
    60  //
    61  type LocalStore struct {
    62  	Validators []ChunkValidator
    63  	memStore   *MemStore
    64  	DbStore    *LDBStore
    65  	mu         sync.Mutex
    66  }
    67  
    68  //
    69  func NewLocalStore(params *LocalStoreParams, mockStore *mock.NodeStore) (*LocalStore, error) {
    70  	ldbparams := NewLDBStoreParams(params.StoreParams, params.ChunkDbPath)
    71  	dbStore, err := NewMockDbStore(ldbparams, mockStore)
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  	return &LocalStore{
    76  		memStore:   NewMemStore(params.StoreParams, dbStore),
    77  		DbStore:    dbStore,
    78  		Validators: params.Validators,
    79  	}, nil
    80  }
    81  
    82  func NewTestLocalStoreForAddr(params *LocalStoreParams) (*LocalStore, error) {
    83  	ldbparams := NewLDBStoreParams(params.StoreParams, params.ChunkDbPath)
    84  	dbStore, err := NewLDBStore(ldbparams)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  	localStore := &LocalStore{
    89  		memStore:   NewMemStore(params.StoreParams, dbStore),
    90  		DbStore:    dbStore,
    91  		Validators: params.Validators,
    92  	}
    93  	return localStore, nil
    94  }
    95  
    96  //
    97  //
    98  //
    99  //
   100  //
   101  //
   102  //
   103  //
   104  //
   105  //
   106  //
   107  //
   108  func (ls *LocalStore) Put(ctx context.Context, chunk *Chunk) {
   109  	valid := true
   110  //
   111  //
   112  	for _, v := range ls.Validators {
   113  		if valid = v.Validate(chunk.Addr, chunk.SData); valid {
   114  			break
   115  		}
   116  	}
   117  	if !valid {
   118  		log.Trace("invalid chunk", "addr", chunk.Addr, "len", len(chunk.SData))
   119  		chunk.SetErrored(ErrChunkInvalid)
   120  		chunk.markAsStored()
   121  		return
   122  	}
   123  
   124  	log.Trace("localstore.put", "addr", chunk.Addr)
   125  
   126  	ls.mu.Lock()
   127  	defer ls.mu.Unlock()
   128  
   129  	chunk.Size = int64(binary.LittleEndian.Uint64(chunk.SData[0:8]))
   130  
   131  	memChunk, err := ls.memStore.Get(ctx, chunk.Addr)
   132  	switch err {
   133  	case nil:
   134  		if memChunk.ReqC == nil {
   135  			chunk.markAsStored()
   136  			return
   137  		}
   138  	case ErrChunkNotFound:
   139  	default:
   140  		chunk.SetErrored(err)
   141  		return
   142  	}
   143  
   144  	ls.DbStore.Put(ctx, chunk)
   145  
   146  //
   147  	newc := NewChunk(chunk.Addr, nil)
   148  	newc.SData = chunk.SData
   149  	newc.Size = chunk.Size
   150  	newc.dbStoredC = chunk.dbStoredC
   151  
   152  	ls.memStore.Put(ctx, newc)
   153  
   154  	if memChunk != nil && memChunk.ReqC != nil {
   155  		close(memChunk.ReqC)
   156  	}
   157  }
   158  
   159  //
   160  //
   161  //
   162  //
   163  func (ls *LocalStore) Get(ctx context.Context, addr Address) (chunk *Chunk, err error) {
   164  	ls.mu.Lock()
   165  	defer ls.mu.Unlock()
   166  
   167  	return ls.get(ctx, addr)
   168  }
   169  
   170  func (ls *LocalStore) get(ctx context.Context, addr Address) (chunk *Chunk, err error) {
   171  	chunk, err = ls.memStore.Get(ctx, addr)
   172  	if err == nil {
   173  		if chunk.ReqC != nil {
   174  			select {
   175  			case <-chunk.ReqC:
   176  			default:
   177  				metrics.GetOrRegisterCounter("localstore.get.errfetching", nil).Inc(1)
   178  				return chunk, ErrFetching
   179  			}
   180  		}
   181  		metrics.GetOrRegisterCounter("localstore.get.cachehit", nil).Inc(1)
   182  		return
   183  	}
   184  	metrics.GetOrRegisterCounter("localstore.get.cachemiss", nil).Inc(1)
   185  	chunk, err = ls.DbStore.Get(ctx, addr)
   186  	if err != nil {
   187  		metrics.GetOrRegisterCounter("localstore.get.error", nil).Inc(1)
   188  		return
   189  	}
   190  	chunk.Size = int64(binary.LittleEndian.Uint64(chunk.SData[0:8]))
   191  	ls.memStore.Put(ctx, chunk)
   192  	return
   193  }
   194  
   195  //
   196  func (ls *LocalStore) GetOrCreateRequest(ctx context.Context, addr Address) (chunk *Chunk, created bool) {
   197  	metrics.GetOrRegisterCounter("localstore.getorcreaterequest", nil).Inc(1)
   198  
   199  	ls.mu.Lock()
   200  	defer ls.mu.Unlock()
   201  
   202  	var err error
   203  	chunk, err = ls.get(ctx, addr)
   204  	if err == nil && chunk.GetErrored() == nil {
   205  		metrics.GetOrRegisterCounter("localstore.getorcreaterequest.hit", nil).Inc(1)
   206  		log.Trace(fmt.Sprintf("LocalStore.GetOrRetrieve: %v found locally", addr))
   207  		return chunk, false
   208  	}
   209  	if err == ErrFetching && chunk.GetErrored() == nil {
   210  		metrics.GetOrRegisterCounter("localstore.getorcreaterequest.errfetching", nil).Inc(1)
   211  		log.Trace(fmt.Sprintf("LocalStore.GetOrRetrieve: %v hit on an existing request %v", addr, chunk.ReqC))
   212  		return chunk, false
   213  	}
   214  //
   215  	metrics.GetOrRegisterCounter("localstore.getorcreaterequest.miss", nil).Inc(1)
   216  	log.Trace(fmt.Sprintf("LocalStore.GetOrRetrieve: %v not found locally. open new request", addr))
   217  	chunk = NewChunk(addr, make(chan bool))
   218  	ls.memStore.Put(ctx, chunk)
   219  	return chunk, true
   220  }
   221  
   222  //
   223  func (ls *LocalStore) RequestsCacheLen() int {
   224  	return ls.memStore.requests.Len()
   225  }
   226  
   227  //
   228  func (ls *LocalStore) Close() {
   229  	ls.DbStore.Close()
   230  }