// handleGetNonDirDataMsg is invoked when a peer receives a dir block message. // It returns the corresponding data block like Factoid block, // EC block, Entry block, and Entry based on directory block's ChainID func (p *peer) handleGetNonDirDataMsg(msg *wire.MsgGetNonDirData) { numAdded := 0 notFound := wire.NewMsgNotFound() // We wait on the this wait channel periodically to prevent queueing // far more data than we can send in a reasonable time, wasting memory. // The waiting occurs after the database fetch for the next one to // provide a little pipelining. var waitChan chan struct{} doneChan := make(chan struct{}, 1) for i, iv := range msg.InvList { var c chan struct{} // If this will be the last message we send. if i == len(msg.InvList)-1 && len(notFound.InvList) == 0 { c = doneChan } else { //if (i+1)%3 == 0 { // Buffered so as to not make the send goroutine block. c = make(chan struct{}, 1) } if iv.Type != wire.InvTypeFactomNonDirBlock { continue } // Is this right? what is iv.hash? blk, err := db.FetchDBlockByHash(iv.Hash.ToFactomHash()) if err != nil { peerLog.Tracef("Unable to fetch requested EC block sha %v: %v", iv.Hash, err) if doneChan != nil { doneChan <- struct{}{} } return } for _, dbEntry := range blk.DBEntries { var err error switch dbEntry.ChainID.String() { case hex.EncodeToString(common.EC_CHAINID[:]): err = p.pushECBlockMsg(dbEntry.KeyMR, c, waitChan) case hex.EncodeToString(common.ADMIN_CHAINID[:]): err = p.pushABlockMsg(dbEntry.KeyMR, c, waitChan) case wire.FChainID.String(): err = p.pushFBlockMsg(dbEntry.KeyMR, c, waitChan) default: err = p.pushEBlockMsg(dbEntry.KeyMR, c, waitChan) //continue } if err != nil { notFound.AddInvVect(iv) // When there is a failure fetching the final entry // and the done channel was sent in due to there // being no outstanding not found inventory, consume // it here because there is now not found inventory // that will use the channel momentarily. if i == len(msg.InvList)-1 && c != nil { <-c } } numAdded++ waitChan = c } } if len(notFound.InvList) != 0 { p.QueueMessage(notFound, doneChan) } // Wait for messages to be sent. We can send quite a lot of data at this // point and this will keep the peer busy for a decent amount of time. // We don't process anything else by them in this time so that we // have an idea of when we should hear back from them - else the idle // timeout could fire when we were only half done sending the blocks. if numAdded > 0 { <-doneChan } }
// handleGetDirDataMsg is invoked when a peer receives a getdata bitcoin message and // is used to deliver block and transaction information. func (p *peer) handleGetDirDataMsg(msg *wire.MsgGetDirData) { numAdded := 0 notFound := wire.NewMsgNotFound() // We wait on the this wait channel periodically to prevent queueing // far more data than we can send in a reasonable time, wasting memory. // The waiting occurs after the database fetch for the next one to // provide a little pipelining. var waitChan chan struct{} doneChan := make(chan struct{}, 1) for i, iv := range msg.InvList { var c chan struct{} // If this will be the last message we send. if i == len(msg.InvList)-1 && len(notFound.InvList) == 0 { c = doneChan } else if (i+1)%3 == 0 { // Buffered so as to not make the send goroutine block. c = make(chan struct{}, 1) } var err error switch iv.Type { //case wire.InvTypeTx: //err = p.pushTxMsg(&iv.Hash, c, waitChan) case wire.InvTypeFactomDirBlock: err = p.pushDirBlockMsg(&iv.Hash, c, waitChan) /* case wire.InvTypeFilteredBlock: err = p.pushMerkleBlockMsg(&iv.Hash, c, waitChan) */ default: peerLog.Warnf("Unknown type in inventory request %d", iv.Type) continue } if err != nil { notFound.AddInvVect(iv) // When there is a failure fetching the final entry // and the done channel was sent in due to there // being no outstanding not found inventory, consume // it here because there is now not found inventory // that will use the channel momentarily. if i == len(msg.InvList)-1 && c != nil { <-c } } numAdded++ waitChan = c } if len(notFound.InvList) != 0 { p.QueueMessage(notFound, doneChan) } // Wait for messages to be sent. We can send quite a lot of data at this // point and this will keep the peer busy for a decent amount of time. // We don't process anything else by them in this time so that we // have an idea of when we should hear back from them - else the idle // timeout could fire when we were only half done sending the blocks. if numAdded > 0 { <-doneChan } }
// handleGetEntryDataMsg is invoked when a peer receives a get entry data message and // is used to deliver entry of EBlock information. func (p *peer) handleGetEntryDataMsg(msg *wire.MsgGetEntryData) { numAdded := 0 notFound := wire.NewMsgNotFound() // We wait on the this wait channel periodically to prevent queueing // far more data than we can send in a reasonable time, wasting memory. // The waiting occurs after the database fetch for the next one to // provide a little pipelining. var waitChan chan struct{} doneChan := make(chan struct{}, 1) for i, iv := range msg.InvList { var c chan struct{} // If this will be the last message we send. if i == len(msg.InvList)-1 && len(notFound.InvList) == 0 { c = doneChan } else { //if (i+1)%3 == 0 { // Buffered so as to not make the send goroutine block. c = make(chan struct{}, 1) } if iv.Type != wire.InvTypeFactomEntry { continue } // Is this right? what is iv.hash? blk, err := db.FetchEBlockByHash(iv.Hash.ToFactomHash()) if err != nil { if doneChan != nil { doneChan <- struct{}{} } return } for _, ebEntry := range blk.Body.EBEntries { //Skip the minute markers if ebEntry.IsMinuteMarker() { continue } var err error err = p.pushEntryMsg(ebEntry, c, waitChan) if err != nil { notFound.AddInvVect(iv) // When there is a failure fetching the final entry // and the done channel was sent in due to there // being no outstanding not found inventory, consume // it here because there is now not found inventory // that will use the channel momentarily. if i == len(msg.InvList)-1 && c != nil { <-c } } numAdded++ waitChan = c } } if len(notFound.InvList) != 0 { p.QueueMessage(notFound, doneChan) } // Wait for messages to be sent. We can send quite a lot of data at this // point and this will keep the peer busy for a decent amount of time. // We don't process anything else by them in this time so that we // have an idea of when we should hear back from them - else the idle // timeout could fire when we were only half done sending the blocks. if numAdded > 0 { <-doneChan } }