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  }