github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/storage/ldbstore.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 12:09:49</date>
    10  //</624342681346117632>
    11  
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  //
    25  //
    26  //
    27  
    28  //
    29  //
    30  //
    31  //
    32  //
    33  
    34  package storage
    35  
    36  import (
    37  	"archive/tar"
    38  	"bytes"
    39  	"context"
    40  	"encoding/binary"
    41  	"encoding/hex"
    42  	"fmt"
    43  	"io"
    44  	"io/ioutil"
    45  	"sort"
    46  	"sync"
    47  
    48  	"github.com/ethereum/go-ethereum/metrics"
    49  	"github.com/ethereum/go-ethereum/rlp"
    50  	"github.com/ethereum/go-ethereum/swarm/chunk"
    51  	"github.com/ethereum/go-ethereum/swarm/log"
    52  	"github.com/ethereum/go-ethereum/swarm/storage/mock"
    53  	"github.com/syndtr/goleveldb/leveldb"
    54  	"github.com/syndtr/goleveldb/leveldb/opt"
    55  )
    56  
    57  const (
    58  	gcArrayFreeRatio = 0.1
    59  maxGCitems       = 5000 //
    60  )
    61  
    62  var (
    63  	keyIndex       = byte(0)
    64  	keyOldData     = byte(1)
    65  	keyAccessCnt   = []byte{2}
    66  	keyEntryCnt    = []byte{3}
    67  	keyDataIdx     = []byte{4}
    68  	keyData        = byte(6)
    69  	keyDistanceCnt = byte(7)
    70  )
    71  
    72  type gcItem struct {
    73  	idx    uint64
    74  	value  uint64
    75  	idxKey []byte
    76  	po     uint8
    77  }
    78  
    79  type LDBStoreParams struct {
    80  	*StoreParams
    81  	Path string
    82  	Po   func(Address) uint8
    83  }
    84  
    85  //
    86  func NewLDBStoreParams(storeparams *StoreParams, path string) *LDBStoreParams {
    87  	return &LDBStoreParams{
    88  		StoreParams: storeparams,
    89  		Path:        path,
    90  		Po:          func(k Address) (ret uint8) { return uint8(Proximity(storeparams.BaseKey[:], k[:])) },
    91  	}
    92  }
    93  
    94  type LDBStore struct {
    95  	db *LDBDatabase
    96  
    97  //
    98  entryCnt  uint64 //
    99  accessCnt uint64 //
   100  dataIdx   uint64 //
   101  	capacity  uint64
   102  	bucketCnt []uint64
   103  
   104  	hashfunc SwarmHasher
   105  	po       func(Address) uint8
   106  
   107  	batchC   chan bool
   108  	batchesC chan struct{}
   109  	batch    *leveldb.Batch
   110  	lock     sync.RWMutex
   111  	quit     chan struct{}
   112  
   113  //
   114  //
   115  //
   116  	encodeDataFunc func(chunk *Chunk) []byte
   117  //
   118  //
   119  //
   120  	getDataFunc func(addr Address) (data []byte, err error)
   121  }
   122  
   123  //
   124  //
   125  //
   126  func NewLDBStore(params *LDBStoreParams) (s *LDBStore, err error) {
   127  	s = new(LDBStore)
   128  	s.hashfunc = params.Hash
   129  	s.quit = make(chan struct{})
   130  
   131  	s.batchC = make(chan bool)
   132  	s.batchesC = make(chan struct{}, 1)
   133  	go s.writeBatches()
   134  	s.batch = new(leveldb.Batch)
   135  //
   136  	s.encodeDataFunc = encodeData
   137  
   138  	s.db, err = NewLDBDatabase(params.Path)
   139  	if err != nil {
   140  		return nil, err
   141  	}
   142  
   143  	s.po = params.Po
   144  	s.setCapacity(params.DbCapacity)
   145  
   146  	s.bucketCnt = make([]uint64, 0x100)
   147  	for i := 0; i < 0x100; i++ {
   148  		k := make([]byte, 2)
   149  		k[0] = keyDistanceCnt
   150  		k[1] = uint8(i)
   151  		cnt, _ := s.db.Get(k)
   152  		s.bucketCnt[i] = BytesToU64(cnt)
   153  		s.bucketCnt[i]++
   154  	}
   155  	data, _ := s.db.Get(keyEntryCnt)
   156  	s.entryCnt = BytesToU64(data)
   157  	s.entryCnt++
   158  	data, _ = s.db.Get(keyAccessCnt)
   159  	s.accessCnt = BytesToU64(data)
   160  	s.accessCnt++
   161  	data, _ = s.db.Get(keyDataIdx)
   162  	s.dataIdx = BytesToU64(data)
   163  	s.dataIdx++
   164  
   165  	return s, nil
   166  }
   167  
   168  //
   169  //
   170  //
   171  func NewMockDbStore(params *LDBStoreParams, mockStore *mock.NodeStore) (s *LDBStore, err error) {
   172  	s, err = NewLDBStore(params)
   173  	if err != nil {
   174  		return nil, err
   175  	}
   176  
   177  //
   178  	if mockStore != nil {
   179  		s.encodeDataFunc = newMockEncodeDataFunc(mockStore)
   180  		s.getDataFunc = newMockGetDataFunc(mockStore)
   181  	}
   182  	return
   183  }
   184  
   185  type dpaDBIndex struct {
   186  	Idx    uint64
   187  	Access uint64
   188  }
   189  
   190  func BytesToU64(data []byte) uint64 {
   191  	if len(data) < 8 {
   192  		return 0
   193  	}
   194  	return binary.BigEndian.Uint64(data)
   195  }
   196  
   197  func U64ToBytes(val uint64) []byte {
   198  	data := make([]byte, 8)
   199  	binary.BigEndian.PutUint64(data, val)
   200  	return data
   201  }
   202  
   203  func (s *LDBStore) updateIndexAccess(index *dpaDBIndex) {
   204  	index.Access = s.accessCnt
   205  }
   206  
   207  func getIndexKey(hash Address) []byte {
   208  	hashSize := len(hash)
   209  	key := make([]byte, hashSize+1)
   210  	key[0] = keyIndex
   211  	copy(key[1:], hash[:])
   212  	return key
   213  }
   214  
   215  func getOldDataKey(idx uint64) []byte {
   216  	key := make([]byte, 9)
   217  	key[0] = keyOldData
   218  	binary.BigEndian.PutUint64(key[1:9], idx)
   219  
   220  	return key
   221  }
   222  
   223  func getDataKey(idx uint64, po uint8) []byte {
   224  	key := make([]byte, 10)
   225  	key[0] = keyData
   226  	key[1] = po
   227  	binary.BigEndian.PutUint64(key[2:], idx)
   228  
   229  	return key
   230  }
   231  
   232  func encodeIndex(index *dpaDBIndex) []byte {
   233  	data, _ := rlp.EncodeToBytes(index)
   234  	return data
   235  }
   236  
   237  func encodeData(chunk *Chunk) []byte {
   238  //
   239  //
   240  //
   241  //
   242  	return append(append([]byte{}, chunk.Addr[:]...), chunk.SData...)
   243  }
   244  
   245  func decodeIndex(data []byte, index *dpaDBIndex) error {
   246  	dec := rlp.NewStream(bytes.NewReader(data), 0)
   247  	return dec.Decode(index)
   248  }
   249  
   250  func decodeData(data []byte, chunk *Chunk) {
   251  	chunk.SData = data[32:]
   252  	chunk.Size = int64(binary.BigEndian.Uint64(data[32:40]))
   253  }
   254  
   255  func decodeOldData(data []byte, chunk *Chunk) {
   256  	chunk.SData = data
   257  	chunk.Size = int64(binary.BigEndian.Uint64(data[0:8]))
   258  }
   259  
   260  func (s *LDBStore) collectGarbage(ratio float32) {
   261  	metrics.GetOrRegisterCounter("ldbstore.collectgarbage", nil).Inc(1)
   262  
   263  	it := s.db.NewIterator()
   264  	defer it.Release()
   265  
   266  	garbage := []*gcItem{}
   267  	gcnt := 0
   268  
   269  	for ok := it.Seek([]byte{keyIndex}); ok && (gcnt < maxGCitems) && (uint64(gcnt) < s.entryCnt); ok = it.Next() {
   270  		itkey := it.Key()
   271  
   272  		if (itkey == nil) || (itkey[0] != keyIndex) {
   273  			break
   274  		}
   275  
   276  //
   277  		key := make([]byte, len(it.Key()))
   278  		copy(key, it.Key())
   279  
   280  		val := it.Value()
   281  
   282  		var index dpaDBIndex
   283  
   284  		hash := key[1:]
   285  		decodeIndex(val, &index)
   286  		po := s.po(hash)
   287  
   288  		gci := &gcItem{
   289  			idxKey: key,
   290  			idx:    index.Idx,
   291  value:  index.Access, //
   292  			po:     po,
   293  		}
   294  
   295  		garbage = append(garbage, gci)
   296  		gcnt++
   297  	}
   298  
   299  	sort.Slice(garbage[:gcnt], func(i, j int) bool { return garbage[i].value < garbage[j].value })
   300  
   301  	cutoff := int(float32(gcnt) * ratio)
   302  	metrics.GetOrRegisterCounter("ldbstore.collectgarbage.delete", nil).Inc(int64(cutoff))
   303  
   304  	for i := 0; i < cutoff; i++ {
   305  		s.delete(garbage[i].idx, garbage[i].idxKey, garbage[i].po)
   306  	}
   307  }
   308  
   309  //
   310  //
   311  func (s *LDBStore) Export(out io.Writer) (int64, error) {
   312  	tw := tar.NewWriter(out)
   313  	defer tw.Close()
   314  
   315  	it := s.db.NewIterator()
   316  	defer it.Release()
   317  	var count int64
   318  	for ok := it.Seek([]byte{keyIndex}); ok; ok = it.Next() {
   319  		key := it.Key()
   320  		if (key == nil) || (key[0] != keyIndex) {
   321  			break
   322  		}
   323  
   324  		var index dpaDBIndex
   325  
   326  		hash := key[1:]
   327  		decodeIndex(it.Value(), &index)
   328  		po := s.po(hash)
   329  		datakey := getDataKey(index.Idx, po)
   330  		log.Trace("store.export", "dkey", fmt.Sprintf("%x", datakey), "dataidx", index.Idx, "po", po)
   331  		data, err := s.db.Get(datakey)
   332  		if err != nil {
   333  			log.Warn(fmt.Sprintf("Chunk %x found but could not be accessed: %v", key[:], err))
   334  			continue
   335  		}
   336  
   337  		hdr := &tar.Header{
   338  			Name: hex.EncodeToString(hash),
   339  			Mode: 0644,
   340  			Size: int64(len(data)),
   341  		}
   342  		if err := tw.WriteHeader(hdr); err != nil {
   343  			return count, err
   344  		}
   345  		if _, err := tw.Write(data); err != nil {
   346  			return count, err
   347  		}
   348  		count++
   349  	}
   350  
   351  	return count, nil
   352  }
   353  
   354  //
   355  func (s *LDBStore) Import(in io.Reader) (int64, error) {
   356  	tr := tar.NewReader(in)
   357  
   358  	var count int64
   359  	var wg sync.WaitGroup
   360  	for {
   361  		hdr, err := tr.Next()
   362  		if err == io.EOF {
   363  			break
   364  		} else if err != nil {
   365  			return count, err
   366  		}
   367  
   368  		if len(hdr.Name) != 64 {
   369  			log.Warn("ignoring non-chunk file", "name", hdr.Name)
   370  			continue
   371  		}
   372  
   373  		keybytes, err := hex.DecodeString(hdr.Name)
   374  		if err != nil {
   375  			log.Warn("ignoring invalid chunk file", "name", hdr.Name, "err", err)
   376  			continue
   377  		}
   378  
   379  		data, err := ioutil.ReadAll(tr)
   380  		if err != nil {
   381  			return count, err
   382  		}
   383  		key := Address(keybytes)
   384  		chunk := NewChunk(key, nil)
   385  		chunk.SData = data[32:]
   386  		s.Put(context.TODO(), chunk)
   387  		wg.Add(1)
   388  		go func() {
   389  			defer wg.Done()
   390  			<-chunk.dbStoredC
   391  		}()
   392  		count++
   393  	}
   394  	wg.Wait()
   395  	return count, nil
   396  }
   397  
   398  func (s *LDBStore) Cleanup() {
   399  //
   400  	var errorsFound, removed, total int
   401  
   402  	it := s.db.NewIterator()
   403  	defer it.Release()
   404  	for ok := it.Seek([]byte{keyIndex}); ok; ok = it.Next() {
   405  		key := it.Key()
   406  		if (key == nil) || (key[0] != keyIndex) {
   407  			break
   408  		}
   409  		total++
   410  		var index dpaDBIndex
   411  		err := decodeIndex(it.Value(), &index)
   412  		if err != nil {
   413  			log.Warn("Cannot decode")
   414  			errorsFound++
   415  			continue
   416  		}
   417  		hash := key[1:]
   418  		po := s.po(hash)
   419  		datakey := getDataKey(index.Idx, po)
   420  		data, err := s.db.Get(datakey)
   421  		if err != nil {
   422  			found := false
   423  
   424  //
   425  			for po = 1; po <= 255; po++ {
   426  				datakey = getDataKey(index.Idx, po)
   427  				data, err = s.db.Get(datakey)
   428  				if err == nil {
   429  					found = true
   430  					break
   431  				}
   432  			}
   433  
   434  			if !found {
   435  				log.Warn(fmt.Sprintf("Chunk %x found but count not be accessed with any po", key[:]))
   436  				errorsFound++
   437  				continue
   438  			}
   439  		}
   440  
   441  		c := &Chunk{}
   442  		ck := data[:32]
   443  		decodeData(data, c)
   444  
   445  		cs := int64(binary.LittleEndian.Uint64(c.SData[:8]))
   446  		log.Trace("chunk", "key", fmt.Sprintf("%x", key[:]), "ck", fmt.Sprintf("%x", ck), "dkey", fmt.Sprintf("%x", datakey), "dataidx", index.Idx, "po", po, "len data", len(data), "len sdata", len(c.SData), "size", cs)
   447  
   448  		if len(c.SData) > chunk.DefaultSize+8 {
   449  			log.Warn("chunk for cleanup", "key", fmt.Sprintf("%x", key[:]), "ck", fmt.Sprintf("%x", ck), "dkey", fmt.Sprintf("%x", datakey), "dataidx", index.Idx, "po", po, "len data", len(data), "len sdata", len(c.SData), "size", cs)
   450  			s.delete(index.Idx, getIndexKey(key[1:]), po)
   451  			removed++
   452  			errorsFound++
   453  		}
   454  	}
   455  
   456  	log.Warn(fmt.Sprintf("Found %v errors out of %v entries. Removed %v chunks.", errorsFound, total, removed))
   457  }
   458  
   459  func (s *LDBStore) ReIndex() {
   460  //
   461  	it := s.db.NewIterator()
   462  	startPosition := []byte{keyOldData}
   463  	it.Seek(startPosition)
   464  	var key []byte
   465  	var errorsFound, total int
   466  	for it.Valid() {
   467  		key = it.Key()
   468  		if (key == nil) || (key[0] != keyOldData) {
   469  			break
   470  		}
   471  		data := it.Value()
   472  		hasher := s.hashfunc()
   473  		hasher.Write(data)
   474  		hash := hasher.Sum(nil)
   475  
   476  		newKey := make([]byte, 10)
   477  		oldCntKey := make([]byte, 2)
   478  		newCntKey := make([]byte, 2)
   479  		oldCntKey[0] = keyDistanceCnt
   480  		newCntKey[0] = keyDistanceCnt
   481  		key[0] = keyData
   482  		key[1] = s.po(Address(key[1:]))
   483  		oldCntKey[1] = key[1]
   484  		newCntKey[1] = s.po(Address(newKey[1:]))
   485  		copy(newKey[2:], key[1:])
   486  		newValue := append(hash, data...)
   487  
   488  		batch := new(leveldb.Batch)
   489  		batch.Delete(key)
   490  		s.bucketCnt[oldCntKey[1]]--
   491  		batch.Put(oldCntKey, U64ToBytes(s.bucketCnt[oldCntKey[1]]))
   492  		batch.Put(newKey, newValue)
   493  		s.bucketCnt[newCntKey[1]]++
   494  		batch.Put(newCntKey, U64ToBytes(s.bucketCnt[newCntKey[1]]))
   495  		s.db.Write(batch)
   496  		it.Next()
   497  	}
   498  	it.Release()
   499  	log.Warn(fmt.Sprintf("Found %v errors out of %v entries", errorsFound, total))
   500  }
   501  
   502  func (s *LDBStore) delete(idx uint64, idxKey []byte, po uint8) {
   503  	metrics.GetOrRegisterCounter("ldbstore.delete", nil).Inc(1)
   504  
   505  	batch := new(leveldb.Batch)
   506  	batch.Delete(idxKey)
   507  	batch.Delete(getDataKey(idx, po))
   508  	s.entryCnt--
   509  	s.bucketCnt[po]--
   510  	cntKey := make([]byte, 2)
   511  	cntKey[0] = keyDistanceCnt
   512  	cntKey[1] = po
   513  	batch.Put(keyEntryCnt, U64ToBytes(s.entryCnt))
   514  	batch.Put(cntKey, U64ToBytes(s.bucketCnt[po]))
   515  	s.db.Write(batch)
   516  }
   517  
   518  func (s *LDBStore) CurrentBucketStorageIndex(po uint8) uint64 {
   519  	s.lock.RLock()
   520  	defer s.lock.RUnlock()
   521  
   522  	return s.bucketCnt[po]
   523  }
   524  
   525  func (s *LDBStore) Size() uint64 {
   526  	s.lock.Lock()
   527  	defer s.lock.Unlock()
   528  	return s.entryCnt
   529  }
   530  
   531  func (s *LDBStore) CurrentStorageIndex() uint64 {
   532  	s.lock.RLock()
   533  	defer s.lock.RUnlock()
   534  	return s.dataIdx
   535  }
   536  
   537  func (s *LDBStore) Put(ctx context.Context, chunk *Chunk) {
   538  	metrics.GetOrRegisterCounter("ldbstore.put", nil).Inc(1)
   539  	log.Trace("ldbstore.put", "key", chunk.Addr)
   540  
   541  	ikey := getIndexKey(chunk.Addr)
   542  	var index dpaDBIndex
   543  
   544  	po := s.po(chunk.Addr)
   545  	s.lock.Lock()
   546  	defer s.lock.Unlock()
   547  
   548  	log.Trace("ldbstore.put: s.db.Get", "key", chunk.Addr, "ikey", fmt.Sprintf("%x", ikey))
   549  	idata, err := s.db.Get(ikey)
   550  	if err != nil {
   551  		s.doPut(chunk, &index, po)
   552  		batchC := s.batchC
   553  		go func() {
   554  			<-batchC
   555  			chunk.markAsStored()
   556  		}()
   557  	} else {
   558  		log.Trace("ldbstore.put: chunk already exists, only update access", "key", chunk.Addr)
   559  		decodeIndex(idata, &index)
   560  		chunk.markAsStored()
   561  	}
   562  	index.Access = s.accessCnt
   563  	s.accessCnt++
   564  	idata = encodeIndex(&index)
   565  	s.batch.Put(ikey, idata)
   566  	select {
   567  	case s.batchesC <- struct{}{}:
   568  	default:
   569  	}
   570  }
   571  
   572  //
   573  func (s *LDBStore) doPut(chunk *Chunk, index *dpaDBIndex, po uint8) {
   574  	data := s.encodeDataFunc(chunk)
   575  	dkey := getDataKey(s.dataIdx, po)
   576  	s.batch.Put(dkey, data)
   577  	index.Idx = s.dataIdx
   578  	s.bucketCnt[po] = s.dataIdx
   579  	s.entryCnt++
   580  	s.dataIdx++
   581  
   582  	cntKey := make([]byte, 2)
   583  	cntKey[0] = keyDistanceCnt
   584  	cntKey[1] = po
   585  	s.batch.Put(cntKey, U64ToBytes(s.bucketCnt[po]))
   586  }
   587  
   588  func (s *LDBStore) writeBatches() {
   589  mainLoop:
   590  	for {
   591  		select {
   592  		case <-s.quit:
   593  			break mainLoop
   594  		case <-s.batchesC:
   595  			s.lock.Lock()
   596  			b := s.batch
   597  			e := s.entryCnt
   598  			d := s.dataIdx
   599  			a := s.accessCnt
   600  			c := s.batchC
   601  			s.batchC = make(chan bool)
   602  			s.batch = new(leveldb.Batch)
   603  			err := s.writeBatch(b, e, d, a)
   604  //
   605  			if err != nil {
   606  				log.Error(fmt.Sprintf("spawn batch write (%d entries): %v", b.Len(), err))
   607  			}
   608  			close(c)
   609  			for e > s.capacity {
   610  //
   611  //
   612  				done := make(chan struct{})
   613  				go func() {
   614  					s.collectGarbage(gcArrayFreeRatio)
   615  					close(done)
   616  				}()
   617  
   618  				e = s.entryCnt
   619  				select {
   620  				case <-s.quit:
   621  					s.lock.Unlock()
   622  					break mainLoop
   623  				case <-done:
   624  				}
   625  			}
   626  			s.lock.Unlock()
   627  		}
   628  	}
   629  	log.Trace(fmt.Sprintf("DbStore: quit batch write loop"))
   630  }
   631  
   632  //
   633  func (s *LDBStore) writeBatch(b *leveldb.Batch, entryCnt, dataIdx, accessCnt uint64) error {
   634  	b.Put(keyEntryCnt, U64ToBytes(entryCnt))
   635  	b.Put(keyDataIdx, U64ToBytes(dataIdx))
   636  	b.Put(keyAccessCnt, U64ToBytes(accessCnt))
   637  	l := b.Len()
   638  	if err := s.db.Write(b); err != nil {
   639  		return fmt.Errorf("unable to write batch: %v", err)
   640  	}
   641  	log.Trace(fmt.Sprintf("batch write (%d entries)", l))
   642  	return nil
   643  }
   644  
   645  //
   646  //
   647  //
   648  //
   649  func newMockEncodeDataFunc(mockStore *mock.NodeStore) func(chunk *Chunk) []byte {
   650  	return func(chunk *Chunk) []byte {
   651  		if err := mockStore.Put(chunk.Addr, encodeData(chunk)); err != nil {
   652  			log.Error(fmt.Sprintf("%T: Chunk %v put: %v", mockStore, chunk.Addr.Log(), err))
   653  		}
   654  		return chunk.Addr[:]
   655  	}
   656  }
   657  
   658  //
   659  func (s *LDBStore) tryAccessIdx(ikey []byte, index *dpaDBIndex) bool {
   660  	idata, err := s.db.Get(ikey)
   661  	if err != nil {
   662  		return false
   663  	}
   664  	decodeIndex(idata, index)
   665  	s.batch.Put(keyAccessCnt, U64ToBytes(s.accessCnt))
   666  	s.accessCnt++
   667  	index.Access = s.accessCnt
   668  	idata = encodeIndex(index)
   669  	s.batch.Put(ikey, idata)
   670  	select {
   671  	case s.batchesC <- struct{}{}:
   672  	default:
   673  	}
   674  	return true
   675  }
   676  
   677  func (s *LDBStore) Get(ctx context.Context, addr Address) (chunk *Chunk, err error) {
   678  	metrics.GetOrRegisterCounter("ldbstore.get", nil).Inc(1)
   679  	log.Trace("ldbstore.get", "key", addr)
   680  
   681  	s.lock.Lock()
   682  	defer s.lock.Unlock()
   683  	return s.get(addr)
   684  }
   685  
   686  func (s *LDBStore) get(addr Address) (chunk *Chunk, err error) {
   687  	var indx dpaDBIndex
   688  
   689  	if s.tryAccessIdx(getIndexKey(addr), &indx) {
   690  		var data []byte
   691  		if s.getDataFunc != nil {
   692  //
   693  			log.Trace("ldbstore.get retrieve with getDataFunc", "key", addr)
   694  			data, err = s.getDataFunc(addr)
   695  			if err != nil {
   696  				return
   697  			}
   698  		} else {
   699  //
   700  			proximity := s.po(addr)
   701  			datakey := getDataKey(indx.Idx, proximity)
   702  			data, err = s.db.Get(datakey)
   703  			log.Trace("ldbstore.get retrieve", "key", addr, "indexkey", indx.Idx, "datakey", fmt.Sprintf("%x", datakey), "proximity", proximity)
   704  			if err != nil {
   705  				log.Trace("ldbstore.get chunk found but could not be accessed", "key", addr, "err", err)
   706  				s.delete(indx.Idx, getIndexKey(addr), s.po(addr))
   707  				return
   708  			}
   709  		}
   710  
   711  		chunk = NewChunk(addr, nil)
   712  		chunk.markAsStored()
   713  		decodeData(data, chunk)
   714  	} else {
   715  		err = ErrChunkNotFound
   716  	}
   717  
   718  	return
   719  }
   720  
   721  //
   722  //
   723  //
   724  func newMockGetDataFunc(mockStore *mock.NodeStore) func(addr Address) (data []byte, err error) {
   725  	return func(addr Address) (data []byte, err error) {
   726  		data, err = mockStore.Get(addr)
   727  		if err == mock.ErrNotFound {
   728  //
   729  			err = ErrChunkNotFound
   730  		}
   731  		return data, err
   732  	}
   733  }
   734  
   735  func (s *LDBStore) updateAccessCnt(addr Address) {
   736  
   737  	s.lock.Lock()
   738  	defer s.lock.Unlock()
   739  
   740  	var index dpaDBIndex
   741  s.tryAccessIdx(getIndexKey(addr), &index) //
   742  
   743  }
   744  
   745  func (s *LDBStore) setCapacity(c uint64) {
   746  	s.lock.Lock()
   747  	defer s.lock.Unlock()
   748  
   749  	s.capacity = c
   750  
   751  	if s.entryCnt > c {
   752  		ratio := float32(1.01) - float32(c)/float32(s.entryCnt)
   753  		if ratio < gcArrayFreeRatio {
   754  			ratio = gcArrayFreeRatio
   755  		}
   756  		if ratio > 1 {
   757  			ratio = 1
   758  		}
   759  		for s.entryCnt > c {
   760  			s.collectGarbage(ratio)
   761  		}
   762  	}
   763  }
   764  
   765  func (s *LDBStore) Close() {
   766  	close(s.quit)
   767  	s.db.Close()
   768  }
   769  
   770  //
   771  func (s *LDBStore) SyncIterator(since uint64, until uint64, po uint8, f func(Address, uint64) bool) error {
   772  	metrics.GetOrRegisterCounter("ldbstore.synciterator", nil).Inc(1)
   773  
   774  	sincekey := getDataKey(since, po)
   775  	untilkey := getDataKey(until, po)
   776  	it := s.db.NewIterator()
   777  	defer it.Release()
   778  
   779  	for ok := it.Seek(sincekey); ok; ok = it.Next() {
   780  		metrics.GetOrRegisterCounter("ldbstore.synciterator.seek", nil).Inc(1)
   781  
   782  		dbkey := it.Key()
   783  		if dbkey[0] != keyData || dbkey[1] != po || bytes.Compare(untilkey, dbkey) < 0 {
   784  			break
   785  		}
   786  		key := make([]byte, 32)
   787  		val := it.Value()
   788  		copy(key, val[:32])
   789  		if !f(Address(key), binary.BigEndian.Uint64(dbkey[2:])) {
   790  			break
   791  		}
   792  	}
   793  	return it.Error()
   794  }
   795  
   796  func databaseExists(path string) bool {
   797  	o := &opt.Options{
   798  		ErrorIfMissing: true,
   799  	}
   800  	tdb, err := leveldb.OpenFile(path, o)
   801  	if err != nil {
   802  		return false
   803  	}
   804  	defer tdb.Close()
   805  	return true
   806  }
   807