github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/ledger/blockledger/fileledger/factory.go (about) 1 /* 2 Copyright hechain. 2022 All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package fileledger 8 9 import ( 10 "os" 11 "path/filepath" 12 "sync" 13 14 "github.com/hechain20/hechain/common/ledger/blkstorage" 15 "github.com/hechain20/hechain/common/ledger/blockledger" 16 "github.com/hechain20/hechain/common/metrics" 17 "github.com/hechain20/hechain/orderer/common/filerepo" 18 ) 19 20 //go:generate counterfeiter -o mock/block_store_provider.go --fake-name BlockStoreProvider . blockStoreProvider 21 type blockStoreProvider interface { 22 Open(ledgerid string) (*blkstorage.BlockStore, error) 23 Drop(ledgerid string) error 24 List() ([]string, error) 25 Close() 26 } 27 28 type fileLedgerFactory struct { 29 blkstorageProvider blockStoreProvider 30 ledgers map[string]*FileLedger 31 mutex sync.Mutex 32 removeFileRepo *filerepo.Repo 33 } 34 35 // GetOrCreate gets an existing ledger (if it exists) or creates it 36 // if it does not. 37 func (f *fileLedgerFactory) GetOrCreate(channelID string) (blockledger.ReadWriter, error) { 38 f.mutex.Lock() 39 defer f.mutex.Unlock() 40 41 // check cache 42 ledger, ok := f.ledgers[channelID] 43 if ok { 44 return ledger, nil 45 } 46 // open fresh 47 blockStore, err := f.blkstorageProvider.Open(channelID) 48 if err != nil { 49 return nil, err 50 } 51 ledger = NewFileLedger(blockStore) 52 f.ledgers[channelID] = ledger 53 return ledger, nil 54 } 55 56 // Remove removes an existing ledger and its indexes. This operation 57 // is blocking. 58 func (f *fileLedgerFactory) Remove(channelID string) error { 59 f.mutex.Lock() 60 defer f.mutex.Unlock() 61 62 if err := f.removeFileRepo.Save(channelID, []byte{}); err != nil && err != os.ErrExist { 63 return err 64 } 65 66 // check cache for open blockstore and, if one exists, 67 // shut it down in order to avoid resource contention 68 ledger, ok := f.ledgers[channelID] 69 if ok { 70 ledger.blockStore.Shutdown() 71 } 72 73 err := f.blkstorageProvider.Drop(channelID) 74 if err != nil { 75 return err 76 } 77 78 delete(f.ledgers, channelID) 79 80 if err := f.removeFileRepo.Remove(channelID); err != nil { 81 return err 82 } 83 84 return nil 85 } 86 87 // ChannelIDs returns the channel IDs the factory is aware of. 88 func (f *fileLedgerFactory) ChannelIDs() []string { 89 channelIDs, err := f.blkstorageProvider.List() 90 if err != nil { 91 logger.Panic(err) 92 } 93 return channelIDs 94 } 95 96 // Close releases all resources acquired by the factory. 97 func (f *fileLedgerFactory) Close() { 98 f.blkstorageProvider.Close() 99 } 100 101 // New creates a new ledger factory 102 func New(directory string, metricsProvider metrics.Provider) (blockledger.Factory, error) { 103 p, err := blkstorage.NewProvider( 104 blkstorage.NewConf(directory, -1), 105 &blkstorage.IndexConfig{ 106 AttrsToIndex: []blkstorage.IndexableAttr{blkstorage.IndexableAttrBlockNum}, 107 }, 108 metricsProvider, 109 ) 110 if err != nil { 111 return nil, err 112 } 113 114 fileRepo, err := filerepo.New(filepath.Join(directory, "pendingops"), "remove") 115 if err != nil { 116 return nil, err 117 } 118 119 factory := &fileLedgerFactory{ 120 blkstorageProvider: p, 121 ledgers: map[string]*FileLedger{}, 122 removeFileRepo: fileRepo, 123 } 124 125 files, err := factory.removeFileRepo.List() 126 if err != nil { 127 return nil, err 128 } 129 for _, fileName := range files { 130 channelID := factory.removeFileRepo.FileToBaseName(fileName) 131 err = factory.Remove(channelID) 132 if err != nil { 133 logger.Errorf("Failed to remove channel %s: %s", channelID, err.Error()) 134 return nil, err 135 } 136 logger.Infof("Removed channel: %s", channelID) 137 } 138 139 return factory, nil 140 }