github.com/sykesm/fabric@v1.1.0-preview.0.20200129034918-2aa12b1a0181/common/ledger/blkstorage/fsblkstorage/fs_blockstore_provider.go (about) 1 /* 2 Copyright IBM Corp. 2017 All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package fsblkstorage 8 9 import ( 10 "os" 11 12 "github.com/hyperledger/fabric/common/ledger/blkstorage" 13 "github.com/hyperledger/fabric/common/ledger/dataformat" 14 "github.com/hyperledger/fabric/common/ledger/util" 15 "github.com/hyperledger/fabric/common/ledger/util/leveldbhelper" 16 "github.com/hyperledger/fabric/common/metrics" 17 "github.com/pkg/errors" 18 ) 19 20 func dataFormatVersion(indexConfig *blkstorage.IndexConfig) string { 21 // in version 2.0 we merged three indexable into one `IndexableAttrTxID` 22 if indexConfig.Contains(blkstorage.IndexableAttrTxID) { 23 return dataformat.Version20 24 } 25 return dataformat.Version1x 26 } 27 28 // FsBlockstoreProvider provides handle to block storage - this is not thread-safe 29 type FsBlockstoreProvider struct { 30 conf *Conf 31 indexConfig *blkstorage.IndexConfig 32 leveldbProvider *leveldbhelper.Provider 33 stats *stats 34 } 35 36 // NewProvider constructs a filesystem based block store provider 37 func NewProvider(conf *Conf, indexConfig *blkstorage.IndexConfig, metricsProvider metrics.Provider) (blkstorage.BlockStoreProvider, error) { 38 dbConf := &leveldbhelper.Conf{ 39 DBPath: conf.getIndexDir(), 40 ExpectedFormatVersion: dataFormatVersion(indexConfig), 41 } 42 43 p, err := leveldbhelper.NewProvider(dbConf) 44 if err != nil { 45 return nil, err 46 } 47 48 dirPath := conf.getChainsDir() 49 if _, err := os.Stat(dirPath); err != nil { 50 if !os.IsNotExist(err) { // NotExist is the only permitted error type 51 return nil, errors.Wrapf(err, "failed to read ledger directory %s", dirPath) 52 } 53 54 logger.Info("Creating new file ledger directory at", dirPath) 55 if err = os.MkdirAll(dirPath, 0755); err != nil { 56 return nil, errors.Wrapf(err, "failed to create ledger directory: %s", dirPath) 57 } 58 } 59 60 // create stats instance at provider level and pass to newFsBlockStore 61 stats := newStats(metricsProvider) 62 return &FsBlockstoreProvider{conf, indexConfig, p, stats}, nil 63 } 64 65 // CreateBlockStore simply calls OpenBlockStore 66 func (p *FsBlockstoreProvider) CreateBlockStore(ledgerid string) (blkstorage.BlockStore, error) { 67 return p.OpenBlockStore(ledgerid) 68 } 69 70 // OpenBlockStore opens a block store for given ledgerid. 71 // If a blockstore is not existing, this method creates one 72 // This method should be invoked only once for a particular ledgerid 73 func (p *FsBlockstoreProvider) OpenBlockStore(ledgerid string) (blkstorage.BlockStore, error) { 74 indexStoreHandle := p.leveldbProvider.GetDBHandle(ledgerid) 75 return newFsBlockStore(ledgerid, p.conf, p.indexConfig, indexStoreHandle, p.stats), nil 76 } 77 78 // Exists tells whether the BlockStore with given id exists 79 func (p *FsBlockstoreProvider) Exists(ledgerid string) (bool, error) { 80 exists, _, err := util.FileExists(p.conf.getLedgerBlockDir(ledgerid)) 81 return exists, err 82 } 83 84 // List lists the ids of the existing ledgers 85 func (p *FsBlockstoreProvider) List() ([]string, error) { 86 return util.ListSubdirs(p.conf.getChainsDir()) 87 } 88 89 // Close closes the FsBlockstoreProvider 90 func (p *FsBlockstoreProvider) Close() { 91 p.leveldbProvider.Close() 92 }