github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/core/ledger/kvledger/kv_ledger_provider.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 kvledger
    18  
    19  import (
    20  	"errors"
    21  
    22  	"github.com/hyperledger/fabric/common/ledger/blkstorage"
    23  	"github.com/hyperledger/fabric/common/ledger/blkstorage/fsblkstorage"
    24  	"github.com/hyperledger/fabric/common/ledger/util/leveldbhelper"
    25  	"github.com/hyperledger/fabric/core/ledger"
    26  	"github.com/hyperledger/fabric/core/ledger/kvledger/history/historydb"
    27  	"github.com/hyperledger/fabric/core/ledger/kvledger/history/historydb/historyleveldb"
    28  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb"
    29  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb/statecouchdb"
    30  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb/stateleveldb"
    31  	"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
    32  )
    33  
    34  var (
    35  	// ErrLedgerIDExists is thrown by a CreateLedger call if a ledger with the given id already exists
    36  	ErrLedgerIDExists = errors.New("LedgerID already exists")
    37  	// ErrNonExistingLedgerID is thrown by a OpenLedger call if a ledger with the given id does not exist
    38  	ErrNonExistingLedgerID = errors.New("LedgerID does not exist")
    39  	// ErrLedgerNotOpened is thrown by a CloseLedger call if a ledger with the given id has not been opened
    40  	ErrLedgerNotOpened = errors.New("Ledger is not opened yet")
    41  )
    42  
    43  // Provider implements interface ledger.PeerLedgerProvider
    44  type Provider struct {
    45  	idStore            *idStore
    46  	blockStoreProvider blkstorage.BlockStoreProvider
    47  	vdbProvider        statedb.VersionedDBProvider
    48  	historydbProvider  historydb.HistoryDBProvider
    49  }
    50  
    51  // NewProvider instantiates a new Provider.
    52  // This is not thread-safe and assumed to be synchronized be the caller
    53  func NewProvider() (ledger.PeerLedgerProvider, error) {
    54  
    55  	logger.Info("Initializing ledger provider")
    56  
    57  	// Initialize the ID store (inventory of chainIds/ledgerIds)
    58  	idStore := openIDStore(ledgerconfig.GetLedgerProviderPath())
    59  
    60  	// Initialize the block storage
    61  	attrsToIndex := []blkstorage.IndexableAttr{
    62  		blkstorage.IndexableAttrBlockHash,
    63  		blkstorage.IndexableAttrBlockNum,
    64  		blkstorage.IndexableAttrTxID,
    65  		blkstorage.IndexableAttrBlockNumTranNum,
    66  		blkstorage.IndexableAttrBlockTxID,
    67  		blkstorage.IndexableAttrTxValidationCode,
    68  	}
    69  	indexConfig := &blkstorage.IndexConfig{AttrsToIndex: attrsToIndex}
    70  	blockStoreProvider := fsblkstorage.NewProvider(
    71  		fsblkstorage.NewConf(ledgerconfig.GetBlockStorePath(), ledgerconfig.GetMaxBlockfileSize()),
    72  		indexConfig)
    73  
    74  	// Initialize the versioned database (state database)
    75  	var vdbProvider statedb.VersionedDBProvider
    76  	if !ledgerconfig.IsCouchDBEnabled() {
    77  		logger.Debug("Constructing leveldb VersionedDBProvider")
    78  		vdbProvider = stateleveldb.NewVersionedDBProvider()
    79  	} else {
    80  		logger.Debug("Constructing CouchDB VersionedDBProvider")
    81  		var err error
    82  		vdbProvider, err = statecouchdb.NewVersionedDBProvider()
    83  		if err != nil {
    84  			return nil, err
    85  		}
    86  	}
    87  
    88  	// Initialize the history database (index for history of values by key)
    89  	var historydbProvider historydb.HistoryDBProvider
    90  	historydbProvider = historyleveldb.NewHistoryDBProvider()
    91  
    92  	logger.Info("ledger provider Initialized")
    93  	return &Provider{idStore, blockStoreProvider, vdbProvider, historydbProvider}, nil
    94  }
    95  
    96  // Create implements the corresponding method from interface ledger.PeerLedgerProvider
    97  func (provider *Provider) Create(ledgerID string) (ledger.PeerLedger, error) {
    98  	exists, err := provider.idStore.ledgerIDExists(ledgerID)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  	if exists {
   103  		return nil, ErrLedgerIDExists
   104  	}
   105  	provider.idStore.createLedgerID(ledgerID)
   106  	return provider.Open(ledgerID)
   107  }
   108  
   109  // Open implements the corresponding method from interface ledger.PeerLedgerProvider
   110  func (provider *Provider) Open(ledgerID string) (ledger.PeerLedger, error) {
   111  
   112  	logger.Debugf("Open() opening kvledger: %s", ledgerID)
   113  
   114  	// Check the ID store to ensure that the chainId/ledgerId exists
   115  	exists, err := provider.idStore.ledgerIDExists(ledgerID)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	if !exists {
   120  		return nil, ErrNonExistingLedgerID
   121  	}
   122  
   123  	// Get the block store for a chain/ledger
   124  	blockStore, err := provider.blockStoreProvider.OpenBlockStore(ledgerID)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  
   129  	// Get the versioned database (state database) for a chain/ledger
   130  	vDB, err := provider.vdbProvider.GetDBHandle(ledgerID)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  
   135  	// Get the history database (index for history of values by key) for a chain/ledger
   136  	historyDB, err := provider.historydbProvider.GetDBHandle(ledgerID)
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  
   141  	// Create a kvLedger for this chain/ledger, which encasulates the underlying data stores
   142  	// (id store, blockstore, state database, history database)
   143  	l, err := newKVLedger(ledgerID, blockStore, vDB, historyDB)
   144  	if err != nil {
   145  		return nil, err
   146  	}
   147  	return l, nil
   148  }
   149  
   150  // Exists implements the corresponding method from interface ledger.PeerLedgerProvider
   151  func (provider *Provider) Exists(ledgerID string) (bool, error) {
   152  	return provider.idStore.ledgerIDExists(ledgerID)
   153  }
   154  
   155  // List implements the corresponding method from interface ledger.PeerLedgerProvider
   156  func (provider *Provider) List() ([]string, error) {
   157  	return provider.idStore.getAllLedgerIds()
   158  }
   159  
   160  // Close implements the corresponding method from interface ledger.PeerLedgerProvider
   161  func (provider *Provider) Close() {
   162  	provider.idStore.close()
   163  	provider.blockStoreProvider.Close()
   164  	provider.vdbProvider.Close()
   165  	provider.historydbProvider.Close()
   166  }
   167  
   168  type idStore struct {
   169  	db *leveldbhelper.DB
   170  }
   171  
   172  func openIDStore(path string) *idStore {
   173  	db := leveldbhelper.CreateDB(&leveldbhelper.Conf{DBPath: path})
   174  	db.Open()
   175  	return &idStore{db}
   176  }
   177  
   178  func (s *idStore) createLedgerID(ledgerID string) error {
   179  	key := []byte(ledgerID)
   180  	val := []byte{}
   181  	err := error(nil)
   182  	if val, err = s.db.Get(key); err != nil {
   183  		return err
   184  	}
   185  	if val != nil {
   186  		return ErrLedgerIDExists
   187  	}
   188  	return s.db.Put(key, val, true)
   189  }
   190  
   191  func (s *idStore) ledgerIDExists(ledgerID string) (bool, error) {
   192  	key := []byte(ledgerID)
   193  	val := []byte{}
   194  	err := error(nil)
   195  	if val, err = s.db.Get(key); err != nil {
   196  		return false, err
   197  	}
   198  	return val != nil, nil
   199  }
   200  
   201  func (s *idStore) getAllLedgerIds() ([]string, error) {
   202  	var ids []string
   203  	itr := s.db.GetIterator(nil, nil)
   204  	itr.First()
   205  	for itr.Valid() {
   206  		key := string(itr.Key())
   207  		ids = append(ids, key)
   208  		itr.Next()
   209  	}
   210  	return ids, nil
   211  }
   212  
   213  func (s *idStore) close() {
   214  	s.db.Close()
   215  }