github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/core/ledger/ledgermgmt/ledger_mgmt.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package ledgermgmt 18 19 import ( 20 "errors" 21 "sync" 22 23 "fmt" 24 25 "github.com/hyperledger/fabric/common/flogging" 26 "github.com/hyperledger/fabric/core/ledger" 27 "github.com/hyperledger/fabric/core/ledger/kvledger" 28 "github.com/hyperledger/fabric/protos/common" 29 "github.com/hyperledger/fabric/protos/utils" 30 ) 31 32 var logger = flogging.MustGetLogger("ledgermgmt") 33 34 // ErrLedgerAlreadyOpened is thrown by a CreateLedger call if a ledger with the given id is already opened 35 var ErrLedgerAlreadyOpened = errors.New("Ledger already opened") 36 37 // ErrLedgerMgmtNotInitialized is thrown when ledger mgmt is used before initializing this 38 var ErrLedgerMgmtNotInitialized = errors.New("ledger mgmt should be initialized before using") 39 40 var openedLedgers map[string]ledger.PeerLedger 41 var ledgerProvider ledger.PeerLedgerProvider 42 var lock sync.Mutex 43 var initialized bool 44 var once sync.Once 45 46 // Initialize initializes ledgermgmt 47 func Initialize() { 48 once.Do(func() { 49 initialize() 50 }) 51 } 52 53 func initialize() { 54 logger.Info("Initializing ledger mgmt") 55 lock.Lock() 56 defer lock.Unlock() 57 initialized = true 58 openedLedgers = make(map[string]ledger.PeerLedger) 59 provider, err := kvledger.NewProvider() 60 if err != nil { 61 panic(fmt.Errorf("Error in instantiating ledger provider: %s", err)) 62 } 63 ledgerProvider = provider 64 logger.Info("ledger mgmt initialized") 65 } 66 67 // CreateLedger creates a new ledger with the given genesis block. 68 // This function guarantees that the creation of ledger and committing the genesis block would an atomic action 69 // The chain id retrieved from the genesis block is treated as a ledger id 70 func CreateLedger(genesisBlock *common.Block) (ledger.PeerLedger, error) { 71 lock.Lock() 72 defer lock.Unlock() 73 if !initialized { 74 return nil, ErrLedgerMgmtNotInitialized 75 } 76 id, err := utils.GetChainIDFromBlock(genesisBlock) 77 if err != nil { 78 return nil, err 79 } 80 81 logger.Infof("Creating ledger [%s] with genesis block", id) 82 l, err := ledgerProvider.Create(genesisBlock) 83 if err != nil { 84 return nil, err 85 } 86 l = wrapLedger(id, l) 87 openedLedgers[id] = l 88 logger.Infof("Created ledger [%s] with genesis block", id) 89 return l, nil 90 } 91 92 // OpenLedger returns a ledger for the given id 93 func OpenLedger(id string) (ledger.PeerLedger, error) { 94 logger.Infof("Opening ledger with id = %s", id) 95 lock.Lock() 96 defer lock.Unlock() 97 if !initialized { 98 return nil, ErrLedgerMgmtNotInitialized 99 } 100 l, ok := openedLedgers[id] 101 if ok { 102 return nil, ErrLedgerAlreadyOpened 103 } 104 l, err := ledgerProvider.Open(id) 105 if err != nil { 106 return nil, err 107 } 108 l = wrapLedger(id, l) 109 openedLedgers[id] = l 110 logger.Infof("Opened ledger with id = %s", id) 111 return l, nil 112 } 113 114 // GetLedgerIDs returns the ids of the ledgers created 115 func GetLedgerIDs() ([]string, error) { 116 lock.Lock() 117 defer lock.Unlock() 118 if !initialized { 119 return nil, ErrLedgerMgmtNotInitialized 120 } 121 return ledgerProvider.List() 122 } 123 124 // Close closes all the opened ledgers and any resources held for ledger management 125 func Close() { 126 logger.Infof("Closing ledger mgmt") 127 lock.Lock() 128 defer lock.Unlock() 129 if !initialized { 130 return 131 } 132 for _, l := range openedLedgers { 133 l.(*closableLedger).closeWithoutLock() 134 } 135 ledgerProvider.Close() 136 openedLedgers = nil 137 logger.Infof("ledger mgmt closed") 138 } 139 140 func wrapLedger(id string, l ledger.PeerLedger) ledger.PeerLedger { 141 return &closableLedger{id, l} 142 } 143 144 // closableLedger extends from actual validated ledger and overwrites the Close method 145 type closableLedger struct { 146 id string 147 ledger.PeerLedger 148 } 149 150 // Close closes the actual ledger and removes the entries from opened ledgers map 151 func (l *closableLedger) Close() { 152 lock.Lock() 153 defer lock.Unlock() 154 l.closeWithoutLock() 155 } 156 157 func (l *closableLedger) closeWithoutLock() { 158 l.PeerLedger.Close() 159 delete(openedLedgers, l.id) 160 }