// peerWantsBlock will check if we have the block in question, // and then if we do, check the ledger for whether or not we should send it. func (bs *BitSwap) peerWantsBlock(p *peer.Peer, want string) { u.DOut("peer [%s] wants block [%s]\n", p.ID.Pretty(), u.Key(want).Pretty()) ledger := bs.getLedger(p) dsk := ds.NewKey(want) blk_i, err := bs.datastore.Get(dsk) if err != nil { if err == ds.ErrNotFound { ledger.Wants(u.Key(want)) } u.PErr("datastore get error: %v\n", err) return } blk, ok := blk_i.([]byte) if !ok { u.PErr("data conversion error.\n") return } if ledger.ShouldSend() { u.DOut("Sending block to peer.\n") bblk, err := blocks.NewBlock(blk) if err != nil { u.PErr("newBlock error: %v\n", err) return } bs.SendBlock(p, bblk) ledger.SentBytes(len(blk)) } else { u.DOut("Decided not to send block.") } }
// GetBlock retrieves a particular block from the service, // Getting it from the datastore using the key (hash). func (s *BlockService) GetBlock(k u.Key) (*blocks.Block, error) { u.DOut("BlockService GetBlock: '%s'\n", k.Pretty()) dsk := ds.NewKey(string(k)) datai, err := s.Datastore.Get(dsk) if err == nil { u.DOut("Blockservice: Got data in datastore.\n") bdata, ok := datai.([]byte) if !ok { return nil, fmt.Errorf("data associated with %s is not a []byte", k) } return &blocks.Block{ Multihash: mh.Multihash(k), Data: bdata, }, nil } else if err == ds.ErrNotFound && s.Remote != nil { u.DOut("Blockservice: Searching bitswap.\n") blk, err := s.Remote.GetBlock(k, time.Second*5) if err != nil { return nil, err } return blk, nil } else { u.DOut("Blockservice GetBlock: Not found.\n") return nil, u.ErrNotFound } }
func (d *Datastore) KeyList() ([]ds.Key, error) { i := d.DB.NewIterator(nil, nil) var keys []ds.Key for ; i.Valid(); i.Next() { keys = append(keys, ds.NewKey(string(i.Key()))) } return keys, nil }
func (dht *IpfsDHT) handleGetValue(p *peer.Peer, pmes *PBDHTMessage) { u.DOut("handleGetValue for key: %s\n", pmes.GetKey()) dskey := ds.NewKey(pmes.GetKey()) resp := &Message{ Response: true, ID: pmes.GetId(), Key: pmes.GetKey(), } iVal, err := dht.datastore.Get(dskey) if err == nil { u.DOut("handleGetValue success!\n") resp.Success = true resp.Value = iVal.([]byte) } else if err == ds.ErrNotFound { // Check if we know any providers for the requested value provs := dht.providers.GetProviders(u.Key(pmes.GetKey())) if len(provs) > 0 { u.DOut("handleGetValue returning %d provider[s]\n", len(provs)) resp.Peers = provs resp.Success = true } else { // No providers? // Find closest peer on given cluster to desired key and reply with that info level := 0 if len(pmes.GetValue()) < 1 { // TODO: maybe return an error? Defaulting isnt a good idea IMO u.PErr("handleGetValue: no routing level specified, assuming 0\n") } else { level = int(pmes.GetValue()[0]) // Using value field to specify cluster level } u.DOut("handleGetValue searching level %d clusters\n", level) closer := dht.routingTables[level].NearestPeer(kb.ConvertKey(u.Key(pmes.GetKey()))) if closer.ID.Equal(dht.self.ID) { u.DOut("Attempted to return self! this shouldnt happen...\n") resp.Peers = nil goto out } // If this peer is closer than the one from the table, return nil if kb.Closer(dht.self.ID, closer.ID, u.Key(pmes.GetKey())) { resp.Peers = nil u.DOut("handleGetValue could not find a closer node than myself.\n") } else { u.DOut("handleGetValue returning a closer peer: '%s'\n", closer.ID.Pretty()) resp.Peers = []*peer.Peer{closer} } } } else { //temp: what other errors can a datastore return? panic(err) } out: mes := swarm.NewMessage(p, resp.ToProtobuf()) dht.netChan.Outgoing <- mes }
func (dht *IpfsDHT) getLocal(key u.Key) ([]byte, error) { dht.dslock.Lock() defer dht.dslock.Unlock() v, err := dht.datastore.Get(ds.NewKey(string(key))) if err != nil { return nil, err } return v.([]byte), nil }
// Store a value in this peer local storage func (dht *IpfsDHT) handlePutValue(p *peer.Peer, pmes *PBDHTMessage) { dht.dslock.Lock() defer dht.dslock.Unlock() dskey := ds.NewKey(pmes.GetKey()) err := dht.datastore.Put(dskey, pmes.GetValue()) if err != nil { // For now, just panic, handle this better later maybe panic(err) } }
// AddBlock adds a particular block to the service, Putting it into the datastore. func (s *BlockService) AddBlock(b *blocks.Block) (u.Key, error) { k := b.Key() dsk := ds.NewKey(string(k)) u.DOut("storing [%s] in datastore\n", k.Pretty()) err := s.Datastore.Put(dsk, b.Data) if err != nil { return k, err } if s.Remote != nil { err = s.Remote.HaveBlock(b) } return k, err }
func (bs *BitSwap) blockReceive(p *peer.Peer, blk *blocks.Block) { u.DOut("blockReceive: %s\n", blk.Key().Pretty()) err := bs.datastore.Put(ds.NewKey(string(blk.Key())), blk.Data) if err != nil { u.PErr("blockReceive error: %v\n", err) return } mes := &swarm.Message{ Peer: p, Data: blk.Data, } bs.listener.Respond(string(blk.Key()), mes) ledger := bs.getLedger(p) ledger.ReceivedBytes(len(blk.Data)) }
func (dht *IpfsDHT) handleGetProviders(p *peer.Peer, pmes *PBDHTMessage) { resp := Message{ Type: PBDHTMessage_GET_PROVIDERS, Key: pmes.GetKey(), ID: pmes.GetId(), Response: true, } has, err := dht.datastore.Has(ds.NewKey(pmes.GetKey())) if err != nil { dht.netChan.Errors <- err } providers := dht.providers.GetProviders(u.Key(pmes.GetKey())) if has { providers = append(providers, dht.self) } if providers == nil || len(providers) == 0 { level := 0 if len(pmes.GetValue()) > 0 { level = int(pmes.GetValue()[0]) } closer := dht.routingTables[level].NearestPeer(kb.ConvertKey(u.Key(pmes.GetKey()))) if kb.Closer(dht.self.ID, closer.ID, u.Key(pmes.GetKey())) { resp.Peers = nil } else { resp.Peers = []*peer.Peer{closer} } } else { resp.Peers = providers resp.Success = true } mes := swarm.NewMessage(p, resp.ToProtobuf()) dht.netChan.Outgoing <- mes }
func (dht *IpfsDHT) putLocal(key u.Key, value []byte) error { return dht.datastore.Put(ds.NewKey(string(key)), value) }