github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/gossip/state/state.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 state
    18  
    19  import (
    20  	"bytes"
    21  	"math/rand"
    22  	"sync"
    23  	"sync/atomic"
    24  	"time"
    25  
    26  	pb "github.com/golang/protobuf/proto"
    27  	"github.com/hyperledger/fabric/core/committer"
    28  	"github.com/hyperledger/fabric/gossip/comm"
    29  	common2 "github.com/hyperledger/fabric/gossip/common"
    30  	"github.com/hyperledger/fabric/gossip/gossip"
    31  	"github.com/hyperledger/fabric/gossip/util"
    32  	"github.com/hyperledger/fabric/protos/common"
    33  	proto "github.com/hyperledger/fabric/protos/gossip"
    34  	"github.com/op/go-logging"
    35  )
    36  
    37  // GossipStateProvider is the interface to acquire sequences of the ledger blocks
    38  // capable to full fill missing blocks by running state replication and
    39  // sending request to get missing block to other nodes
    40  type GossipStateProvider interface {
    41  	// Retrieve block with sequence number equal to index
    42  	GetBlock(index uint64) *common.Block
    43  
    44  	AddPayload(payload *proto.Payload) error
    45  
    46  	// Stop terminates state transfer object
    47  	Stop()
    48  }
    49  
    50  var remoteStateMsgFilter = func(message interface{}) bool {
    51  	return message.(proto.ReceivedMessage).GetGossipMessage().IsRemoteStateMessage()
    52  }
    53  
    54  const (
    55  	defPollingPeriod       = 200 * time.Millisecond
    56  	defAntiEntropyInterval = 10 * time.Second
    57  )
    58  
    59  // GossipStateProviderImpl the implementation of the GossipStateProvider interface
    60  // the struct to handle in memory sliding window of
    61  // new ledger block to be acquired by hyper ledger
    62  type GossipStateProviderImpl struct {
    63  	// Chain id
    64  	chainID string
    65  
    66  	// The gossiping service
    67  	gossip gossip.Gossip
    68  
    69  	// Channel to read gossip messages from
    70  	gossipChan <-chan *proto.GossipMessage
    71  
    72  	commChan <-chan proto.ReceivedMessage
    73  
    74  	// Flag which signals for termination
    75  	stopFlag int32
    76  
    77  	mutex sync.RWMutex
    78  
    79  	// Queue of payloads which wasn't acquired yet
    80  	payloads PayloadsBuffer
    81  
    82  	committer committer.Committer
    83  
    84  	logger *logging.Logger
    85  
    86  	done sync.WaitGroup
    87  }
    88  
    89  // NewGossipStateProvider creates initialized instance of gossip state provider
    90  func NewGossipStateProvider(chainID string, g gossip.Gossip, committer committer.Committer) GossipStateProvider {
    91  	logger := util.GetLogger(util.LoggingStateModule, "")
    92  
    93  	gossipChan, _ := g.Accept(func(message interface{}) bool {
    94  		// Get only data messages
    95  		return message.(*proto.GossipMessage).IsDataMsg() &&
    96  			bytes.Equal(message.(*proto.GossipMessage).Channel, []byte(chainID))
    97  	}, false)
    98  
    99  	// Filter message which are only relevant for state transfer
   100  	_, commChan := g.Accept(remoteStateMsgFilter, true)
   101  
   102  	height, err := committer.LedgerHeight()
   103  
   104  	if err != nil {
   105  		logger.Error("Could not read ledger info to obtain current ledger height due to: ", err)
   106  		// Exiting as without ledger it will be impossible
   107  		// to deliver new blocks
   108  		return nil
   109  	}
   110  
   111  	s := &GossipStateProviderImpl{
   112  		chainID: chainID,
   113  
   114  		// Instance of the gossip
   115  		gossip: g,
   116  
   117  		// Channel to read new messages from
   118  		gossipChan: gossipChan,
   119  
   120  		// Channel to read direct messages from other peers
   121  		commChan: commChan,
   122  
   123  		stopFlag: 0,
   124  		// Create a queue for payload received
   125  		payloads: NewPayloadsBuffer(height),
   126  
   127  		committer: committer,
   128  
   129  		logger: logger,
   130  	}
   131  
   132  	state := NewNodeMetastate(height - 1)
   133  
   134  	s.logger.Infof("Updating node metadata information, current ledger sequence is at = %d, next expected block is = %d", state.LedgerHeight, s.payloads.Next())
   135  	bytes, err := state.Bytes()
   136  	if err == nil {
   137  		s.logger.Debug("Updating gossip metadate state", state)
   138  		g.UpdateChannelMetadata(bytes, common2.ChainID(s.chainID))
   139  	} else {
   140  		s.logger.Errorf("Unable to serialize node meta state, error = %s", err)
   141  	}
   142  
   143  	s.done.Add(3)
   144  
   145  	// Listen for incoming communication
   146  	go s.listen()
   147  	// Deliver in order messages into the incoming channel
   148  	go s.deliverPayloads()
   149  	// Execute anti entropy to fill missing gaps
   150  	go s.antiEntropy()
   151  
   152  	return s
   153  }
   154  
   155  func (s *GossipStateProviderImpl) listen() {
   156  	for !s.isDone() {
   157  		// Do not block on waiting message from channel
   158  		// check each 500ms whenever is done indicates to
   159  		// finish
   160  	next:
   161  		select {
   162  		case msg := <-s.gossipChan:
   163  			{
   164  				s.logger.Debug("Received new message via gossip channel")
   165  				go s.queueNewMessage(msg)
   166  			}
   167  		case msg := <-s.commChan:
   168  			{
   169  				s.logger.Debug("Direct message ", msg)
   170  				go s.directMessage(msg)
   171  			}
   172  		case <-time.After(defPollingPeriod):
   173  			break next
   174  		}
   175  	}
   176  	s.logger.Debug("Stop listening for new messages")
   177  	s.done.Done()
   178  }
   179  
   180  func (s *GossipStateProviderImpl) directMessage(msg proto.ReceivedMessage) {
   181  	s.logger.Debug("[ENTER] -> directMessage")
   182  	defer s.logger.Debug("[EXIT] ->  directMessage")
   183  
   184  	if msg == nil {
   185  		s.logger.Error("Got nil message via end-to-end channel, should not happen!")
   186  		return
   187  	}
   188  
   189  	if !bytes.Equal(msg.GetGossipMessage().Channel, []byte(s.chainID)) {
   190  		s.logger.Warning("Received state transfer request for channel",
   191  			string(msg.GetGossipMessage().Channel), "while expecting channel", s.chainID, "skipping request...")
   192  		return
   193  	}
   194  
   195  	incoming := msg.GetGossipMessage()
   196  
   197  	if incoming.GetStateRequest() != nil {
   198  		s.handleStateRequest(msg)
   199  	} else if incoming.GetStateResponse() != nil {
   200  		s.handleStateResponse(msg)
   201  	}
   202  }
   203  
   204  func (s *GossipStateProviderImpl) handleStateRequest(msg proto.ReceivedMessage) {
   205  	request := msg.GetGossipMessage().GetStateRequest()
   206  	response := &proto.RemoteStateResponse{Payloads: make([]*proto.Payload, 0)}
   207  	for _, seqNum := range request.SeqNums {
   208  		s.logger.Debug("Reading block ", seqNum, " from the committer service")
   209  		blocks := s.committer.GetBlocks([]uint64{seqNum})
   210  
   211  		if blocks == nil || len(blocks) < 1 {
   212  			s.logger.Errorf("Wasn't able to read block with sequence number %d from ledger, skipping....", seqNum)
   213  			continue
   214  		}
   215  
   216  		blockBytes, err := pb.Marshal(blocks[0])
   217  		if err != nil {
   218  			s.logger.Errorf("Could not marshal block: %s", err)
   219  		}
   220  
   221  		response.Payloads = append(response.Payloads, &proto.Payload{
   222  			SeqNum: seqNum,
   223  			Data:   blockBytes,
   224  			Hash:   string(blocks[0].Header.Hash()),
   225  		})
   226  	}
   227  	// Sending back response with missing blocks
   228  	msg.Respond(&proto.GossipMessage{
   229  		Nonce:   0,
   230  		Tag:     proto.GossipMessage_CHAN_OR_ORG,
   231  		Channel: []byte(s.chainID),
   232  		Content: &proto.GossipMessage_StateResponse{response},
   233  	})
   234  }
   235  
   236  func (s *GossipStateProviderImpl) handleStateResponse(msg proto.ReceivedMessage) {
   237  	response := msg.GetGossipMessage().GetStateResponse()
   238  	for _, payload := range response.GetPayloads() {
   239  		s.logger.Debugf("Received payload with sequence number %d.", payload.SeqNum)
   240  		err := s.payloads.Push(payload)
   241  		if err != nil {
   242  			s.logger.Warningf("Payload with sequence number %d was received earlier", payload.SeqNum)
   243  		}
   244  	}
   245  }
   246  
   247  // Internal function to check whenever we need to finish listening
   248  // for new messages to arrive
   249  func (s *GossipStateProviderImpl) isDone() bool {
   250  	return atomic.LoadInt32(&s.stopFlag) == 1
   251  }
   252  
   253  // Stop function send halting signal to all go routines
   254  func (s *GossipStateProviderImpl) Stop() {
   255  	atomic.StoreInt32(&s.stopFlag, 1)
   256  	s.done.Wait()
   257  	s.committer.Close()
   258  }
   259  
   260  // New message notification/handler
   261  func (s *GossipStateProviderImpl) queueNewMessage(msg *proto.GossipMessage) {
   262  	if !bytes.Equal(msg.Channel, []byte(s.chainID)) {
   263  		s.logger.Warning("Received state transfer request for channel",
   264  			string(msg.Channel), "while expecting channel", s.chainID, "skipping request...")
   265  		return
   266  	}
   267  
   268  	dataMsg := msg.GetDataMsg()
   269  	if dataMsg != nil {
   270  		// Add new payload to ordered set
   271  		s.logger.Debugf("Received new payload with sequence number = [%d]", dataMsg.Payload.SeqNum)
   272  		s.payloads.Push(dataMsg.GetPayload())
   273  	} else {
   274  		s.logger.Debug("Gossip message received is not of data message type, usually this should not happen.")
   275  	}
   276  }
   277  
   278  func (s *GossipStateProviderImpl) deliverPayloads() {
   279  	for !s.isDone() {
   280  	next:
   281  		select {
   282  		// Wait for notification that next seq has arrived
   283  		case <-s.payloads.Ready():
   284  			{
   285  				s.logger.Debugf("Ready to transfer payloads to the ledger, next sequence number is = [%d]", s.payloads.Next())
   286  				// Collect all subsequent payloads
   287  				for payload := s.payloads.Pop(); payload != nil; payload = s.payloads.Pop() {
   288  					rawblock := &common.Block{}
   289  					if err := pb.Unmarshal(payload.Data, rawblock); err != nil {
   290  						s.logger.Errorf("Error getting block with seqNum = %d due to (%s)...dropping block", payload.SeqNum, err)
   291  						continue
   292  					}
   293  					s.logger.Debug("New block with sequence number ", payload.SeqNum, " transactions num ", len(rawblock.Data.Data))
   294  					s.commitBlock(rawblock, payload.SeqNum)
   295  				}
   296  			}
   297  		case <-time.After(defPollingPeriod):
   298  			{
   299  				break next
   300  			}
   301  		}
   302  	}
   303  	s.logger.Debug("State provider has been stoped, finishing to push new blocks.")
   304  	s.done.Done()
   305  }
   306  
   307  func (s *GossipStateProviderImpl) antiEntropy() {
   308  	checkPoint := time.Now()
   309  	for !s.isDone() {
   310  		time.Sleep(defPollingPeriod)
   311  		if time.Since(checkPoint).Nanoseconds() <= defAntiEntropyInterval.Nanoseconds() {
   312  			continue
   313  		}
   314  		checkPoint = time.Now()
   315  
   316  		current, _ := s.committer.LedgerHeight()
   317  		max, _ := s.committer.LedgerHeight()
   318  
   319  		for _, p := range s.gossip.PeersOfChannel(common2.ChainID(s.chainID)) {
   320  			if state, err := FromBytes(p.Metadata); err == nil {
   321  				if max < state.LedgerHeight {
   322  					max = state.LedgerHeight
   323  				}
   324  			}
   325  		}
   326  
   327  		if current == max {
   328  			continue
   329  		}
   330  
   331  		s.requestBlocksInRange(uint64(current), uint64(max))
   332  	}
   333  	s.logger.Debug("Stateprovider stopped, stopping anti entropy procedure.")
   334  	s.done.Done()
   335  }
   336  
   337  // GetBlocksInRange capable to acquire blocks with sequence
   338  // numbers in the range [start...end].
   339  func (s *GossipStateProviderImpl) requestBlocksInRange(start uint64, end uint64) {
   340  	var peers []*comm.RemotePeer
   341  	// Filtering peers which might have relevant blocks
   342  	for _, netMember := range s.gossip.PeersOfChannel(common2.ChainID(s.chainID)) {
   343  		nodeMetadata, err := FromBytes(netMember.Metadata)
   344  		if err == nil {
   345  			if nodeMetadata.LedgerHeight >= end {
   346  				peers = append(peers, &comm.RemotePeer{Endpoint: netMember.PreferredEndpoint(), PKIID: netMember.PKIid})
   347  			}
   348  		} else {
   349  			s.logger.Errorf("Unable to de-serialize node meta state, error = %s", err)
   350  		}
   351  	}
   352  
   353  	n := len(peers)
   354  	if n == 0 {
   355  		s.logger.Warningf("There is not peer nodes to ask for missing blocks in range [%d, %d)", start, end)
   356  		return
   357  	}
   358  	// Select peers to ask for blocks
   359  	peer := peers[rand.Intn(n)]
   360  	s.logger.Infof("State transfer, with peer %s, the min available sequence number %d next block %d", peer.Endpoint, start, end)
   361  
   362  	request := &proto.RemoteStateRequest{
   363  		SeqNums: make([]uint64, 0),
   364  	}
   365  
   366  	for i := start; i <= end; i++ {
   367  		request.SeqNums = append(request.SeqNums, uint64(i))
   368  	}
   369  
   370  	s.logger.Debug("Sending direct request to complete missing blocks,", request, "for chain", s.chainID)
   371  	s.gossip.Send(&proto.GossipMessage{
   372  		Nonce:   0,
   373  		Tag:     proto.GossipMessage_CHAN_OR_ORG,
   374  		Channel: []byte(s.chainID),
   375  		Content: &proto.GossipMessage_StateRequest{request},
   376  	}, peer)
   377  }
   378  
   379  // GetBlock return ledger block given its sequence number as a parameter
   380  func (s *GossipStateProviderImpl) GetBlock(index uint64) *common.Block {
   381  	// Try to read missing block from the ledger, should return no nil with
   382  	// content including at least one block
   383  	if blocks := s.committer.GetBlocks([]uint64{index}); blocks != nil && len(blocks) > 0 {
   384  		return blocks[0]
   385  	}
   386  
   387  	return nil
   388  }
   389  
   390  // AddPayload add new payload into state
   391  func (s *GossipStateProviderImpl) AddPayload(payload *proto.Payload) error {
   392  	s.logger.Debug("Adding new payload into the buffer, seqNum = ", payload.SeqNum)
   393  	return s.payloads.Push(payload)
   394  }
   395  
   396  func (s *GossipStateProviderImpl) commitBlock(block *common.Block, seqNum uint64) error {
   397  	if err := s.committer.Commit(block); err != nil {
   398  		s.logger.Errorf("Got error while committing(%s)", err)
   399  		return err
   400  	}
   401  
   402  	// Update ledger level within node metadata
   403  	state := NewNodeMetastate(seqNum)
   404  	// Decode state to byte array
   405  	bytes, err := state.Bytes()
   406  	if err == nil {
   407  		s.gossip.UpdateChannelMetadata(bytes, common2.ChainID(s.chainID))
   408  	} else {
   409  		s.logger.Errorf("Unable to serialize node meta state, error = %s", err)
   410  	}
   411  
   412  	s.logger.Debugf("Channel [%s]: Created block [%d] with %d transaction(s)", s.chainID, block.Header.Number, len(block.Data.Data))
   413  	return nil
   414  }