From a0ab80be6e42db939a34b109bc8481b857c096e8 Mon Sep 17 00:00:00 2001 From: Brian Tiger Chow Date: Thu, 18 Sep 2014 14:22:07 -0700 Subject: [PATCH 1/7] fix(bitswap) implement, test concrete strategist --- bitswap/bitswap.go | 2 +- bitswap/strategy/ledger.go | 10 ++-- bitswap/strategy/strategy.go | 77 +++++++++++++++++++++---------- bitswap/strategy/strategy_test.go | 52 +++++++++++++++++++++ 4 files changed, 113 insertions(+), 28 deletions(-) create mode 100644 bitswap/strategy/strategy_test.go diff --git a/bitswap/bitswap.go b/bitswap/bitswap.go index fcc3128b042..5c24e2c9702 100644 --- a/bitswap/bitswap.go +++ b/bitswap/bitswap.go @@ -55,7 +55,7 @@ func NewSession(parent context.Context, s bsnet.NetworkService, p *peer.Peer, d bs := &bitswap{ blockstore: blockstore.NewBlockstore(d), notifications: notifications.New(), - strategist: strategy.New(d), + strategist: strategy.New(), peer: p, routing: directory, sender: bsnet.NewNetworkAdapter(s, &receiver), diff --git a/bitswap/strategy/ledger.go b/bitswap/strategy/ledger.go index 0ee3a1021e0..24bf4d4a87b 100644 --- a/bitswap/strategy/ledger.go +++ b/bitswap/strategy/ledger.go @@ -12,6 +12,13 @@ import ( // access/lookups. type keySet map[u.Key]struct{} +func newLedger(p *peer.Peer, strategy strategyFunc) *ledger { + return &ledger{ + Strategy: strategy, + Partner: p, + } +} + // ledger stores the data exchange relationship between two peers. type ledger struct { lock sync.RWMutex @@ -37,9 +44,6 @@ type ledger struct { Strategy strategyFunc } -// LedgerMap lists Ledgers by their Partner key. -type ledgerMap map[u.Key]*ledger - func (l *ledger) ShouldSend() bool { l.lock.Lock() defer l.lock.Unlock() diff --git a/bitswap/strategy/strategy.go b/bitswap/strategy/strategy.go index a304669c71a..8d6946dc177 100644 --- a/bitswap/strategy/strategy.go +++ b/bitswap/strategy/strategy.go @@ -3,56 +3,85 @@ package strategy import ( "errors" - ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/datastore.go" bsmsg "github.com/jbenet/go-ipfs/bitswap/message" "github.com/jbenet/go-ipfs/peer" u "github.com/jbenet/go-ipfs/util" ) // TODO declare thread-safe datastore -func New(d ds.Datastore) Strategist { +func New() Strategist { return &strategist{ - datastore: d, - peers: ledgerMap{}, + ledgerMap: ledgerMap{}, + strategyFunc: yesManStrategy, } } type strategist struct { - datastore ds.Datastore // FIXME(brian): enforce thread-safe datastore - - peers ledgerMap + ledgerMap + strategyFunc } -// Peers returns a list of this instance is connected to +// LedgerMap lists Ledgers by their Partner key. +type ledgerMap map[peerKey]*ledger + +// FIXME share this externally +type peerKey u.Key + +// Peers returns a list of peers func (s *strategist) Peers() []*peer.Peer { - response := make([]*peer.Peer, 0) // TODO + response := make([]*peer.Peer, 0) + for _, ledger := range s.ledgerMap { + response = append(response, ledger.Partner) + } return response } -func (s *strategist) IsWantedByPeer(u.Key, *peer.Peer) bool { - return true // TODO +func (s *strategist) IsWantedByPeer(k u.Key, p *peer.Peer) bool { + ledger := s.ledger(p) + return ledger.WantListContains(k) } -func (s *strategist) ShouldSendToPeer(u.Key, *peer.Peer) bool { - return true // TODO +func (s *strategist) ShouldSendToPeer(k u.Key, p *peer.Peer) bool { + ledger := s.ledger(p) + return ledger.ShouldSend() } func (s *strategist) Seed(int64) { // TODO } -func (s *strategist) MessageReceived(*peer.Peer, bsmsg.BitSwapMessage) error { - // TODO add peer to partners if doesn't already exist. - // TODO initialize ledger for peer if doesn't already exist - // TODO get wantlist from message and update contents in local wantlist for peer - // TODO acknowledge receipt of blocks and do accounting in ledger +func (s *strategist) MessageReceived(p *peer.Peer, m bsmsg.BitSwapMessage) error { + l := s.ledger(p) + for _, key := range m.Wantlist() { + l.Wants(key) + } + for _, block := range m.Blocks() { + // FIXME extract blocks.NumBytes(block) or block.NumBytes() method + l.ReceivedBytes(len(block.Data)) + } return errors.New("TODO") } -func (s *strategist) MessageSent(*peer.Peer, bsmsg.BitSwapMessage) error { - // TODO add peer to partners if doesn't already exist. - // TODO initialize ledger for peer if doesn't already exist - // TODO add block to my wantlist - // TODO acknowledge receipt of blocks and do accounting in ledger - return errors.New("TODO") +// TODO add contents of m.WantList() to my local wantlist? NB: could introduce +// race conditions where I send a message, but MessageSent gets handled after +// MessageReceived. The information in the local wantlist could become +// inconsistent. Would need to ensure that Sends and acknowledgement of the +// send happen atomically + +func (s *strategist) MessageSent(p *peer.Peer, m bsmsg.BitSwapMessage) error { + l := s.ledger(p) + for _, block := range m.Blocks() { + l.SentBytes(len(block.Data)) + } + return nil +} + +// ledger lazily instantiates a ledger +func (s *strategist) ledger(p *peer.Peer) *ledger { + l, ok := s.ledgerMap[peerKey(p.Key())] + if !ok { + l = newLedger(p, s.strategyFunc) + s.ledgerMap[peerKey(p.Key())] = l + } + return l } diff --git a/bitswap/strategy/strategy_test.go b/bitswap/strategy/strategy_test.go new file mode 100644 index 00000000000..e8ef9285ceb --- /dev/null +++ b/bitswap/strategy/strategy_test.go @@ -0,0 +1,52 @@ +package strategy + +import ( + "testing" + + message "github.com/jbenet/go-ipfs/bitswap/message" + "github.com/jbenet/go-ipfs/peer" +) + +type peerAndStrategist struct { + *peer.Peer + Strategist +} + +func newPeerAndStrategist(idStr string) peerAndStrategist { + return peerAndStrategist{ + Peer: &peer.Peer{ID: peer.ID(idStr)}, + Strategist: New(), + } +} + +func TestPeerIsAddedToPeersWhenMessageReceivedOrSent(t *testing.T) { + + sanfrancisco := newPeerAndStrategist("sf") + seattle := newPeerAndStrategist("sea") + + m := message.New() + + sanfrancisco.MessageSent(seattle.Peer, m) + seattle.MessageReceived(sanfrancisco.Peer, m) + + if seattle.Peer.Key() == sanfrancisco.Peer.Key() { + t.Fatal("Sanity Check: Peers have same Key!") + } + + if !peerIsPartner(seattle.Peer, sanfrancisco.Strategist) { + t.Fatal("Peer wasn't added as a Partner") + } + + if !peerIsPartner(sanfrancisco.Peer, seattle.Strategist) { + t.Fatal("Peer wasn't added as a Partner") + } +} + +func peerIsPartner(p *peer.Peer, s Strategist) bool { + for _, partner := range s.Peers() { + if partner.Key() == p.Key() { + return true + } + } + return false +} From 27dd84c32c7b257719b06727e0f1b8eb915cf304 Mon Sep 17 00:00:00 2001 From: Brian Tiger Chow Date: Thu, 18 Sep 2014 14:28:20 -0700 Subject: [PATCH 2/7] fix(bitswap) init wantlist + test that a partners wants are remembered by message receiver --- bitswap/strategy/ledger.go | 1 + bitswap/strategy/strategy_test.go | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/bitswap/strategy/ledger.go b/bitswap/strategy/ledger.go index 24bf4d4a87b..34f3010552f 100644 --- a/bitswap/strategy/ledger.go +++ b/bitswap/strategy/ledger.go @@ -14,6 +14,7 @@ type keySet map[u.Key]struct{} func newLedger(p *peer.Peer, strategy strategyFunc) *ledger { return &ledger{ + wantList: keySet{}, Strategy: strategy, Partner: p, } diff --git a/bitswap/strategy/strategy_test.go b/bitswap/strategy/strategy_test.go index e8ef9285ceb..4adff29a0a1 100644 --- a/bitswap/strategy/strategy_test.go +++ b/bitswap/strategy/strategy_test.go @@ -5,6 +5,7 @@ import ( message "github.com/jbenet/go-ipfs/bitswap/message" "github.com/jbenet/go-ipfs/peer" + "github.com/jbenet/go-ipfs/util/testutil" ) type peerAndStrategist struct { @@ -19,6 +20,23 @@ func newPeerAndStrategist(idStr string) peerAndStrategist { } } +func TestBlockRecordedAsWantedAfterMessageReceived(t *testing.T) { + beggar := newPeerAndStrategist("can't be chooser") + chooser := newPeerAndStrategist("chooses JIF") + + block := testutil.NewBlockOrFail(t, "data wanted by beggar") + + messageFromBeggarToChooser := message.New() + messageFromBeggarToChooser.AppendWanted(block.Key()) + + chooser.MessageReceived(beggar.Peer, messageFromBeggarToChooser) + // for this test, doesn't matter if you record that beggar sent + + if !chooser.IsWantedByPeer(block.Key(), beggar.Peer) { + t.Fatal("chooser failed to record that beggar wants block") + } +} + func TestPeerIsAddedToPeersWhenMessageReceivedOrSent(t *testing.T) { sanfrancisco := newPeerAndStrategist("sf") From b0bb9244a4ab3593b3517bc7178b52e845143165 Mon Sep 17 00:00:00 2001 From: Brian Tiger Chow Date: Thu, 18 Sep 2014 15:02:16 -0700 Subject: [PATCH 3/7] style(bitswap) rename strategist -> strategy --- bitswap/bitswap.go | 22 +++++++++++----------- bitswap/strategy/interface.go | 6 +++--- bitswap/strategy/strategy.go | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/bitswap/bitswap.go b/bitswap/bitswap.go index 5c24e2c9702..ebbdd7b1101 100644 --- a/bitswap/bitswap.go +++ b/bitswap/bitswap.go @@ -41,10 +41,10 @@ type bitswap struct { notifications notifications.PubSub - // strategist listens to network traffic and makes decisions about how to + // strategy listens to network traffic and makes decisions about how to // interact with partners. - // TODO(brian): save the strategist's state to the datastore - strategist strategy.Strategist + // TODO(brian): save the strategy's state to the datastore + strategy strategy.Strategy } // NewSession initializes a bitswap session. @@ -55,7 +55,7 @@ func NewSession(parent context.Context, s bsnet.NetworkService, p *peer.Peer, d bs := &bitswap{ blockstore: blockstore.NewBlockstore(d), notifications: notifications.New(), - strategist: strategy.New(), + strategy: strategy.New(), peer: p, routing: directory, sender: bsnet.NewNetworkAdapter(s, &receiver), @@ -112,7 +112,7 @@ func (bs *bitswap) getBlock(k u.Key, p *peer.Peer, timeout time.Duration) (*bloc // that accounting is _always_ performed when SendMessage and // ReceiveMessage are called bs.sender.SendMessage(ctx, p, message) - bs.strategist.MessageSent(p, message) + bs.strategy.MessageSent(p, message) block, ok := <-blockChannel if !ok { @@ -122,9 +122,9 @@ func (bs *bitswap) getBlock(k u.Key, p *peer.Peer, timeout time.Duration) (*bloc } func (bs *bitswap) sendToPeersThatWant(block blocks.Block) { - for _, p := range bs.strategist.Peers() { - if bs.strategist.IsWantedByPeer(block.Key(), p) { - if bs.strategist.ShouldSendToPeer(block.Key(), p) { + for _, p := range bs.strategy.Peers() { + if bs.strategy.BlockIsWantedByPeer(block.Key(), p) { + if bs.strategy.ShouldSendBlockToPeer(block.Key(), p) { go bs.send(p, block) } } @@ -144,7 +144,7 @@ func (bs *bitswap) send(p *peer.Peer, b blocks.Block) { message.AppendBlock(b) // FIXME(brian): pass ctx bs.sender.SendMessage(context.Background(), p, message) - bs.strategist.MessageSent(p, message) + bs.strategy.MessageSent(p, message) } // TODO(brian): handle errors @@ -152,7 +152,7 @@ func (bs *bitswap) ReceiveMessage( ctx context.Context, sender *peer.Peer, incoming bsmsg.BitSwapMessage) ( *peer.Peer, bsmsg.BitSwapMessage, error) { - bs.strategist.MessageReceived(sender, incoming) + bs.strategy.MessageReceived(sender, incoming) if incoming.Blocks() != nil { for _, block := range incoming.Blocks() { @@ -163,7 +163,7 @@ func (bs *bitswap) ReceiveMessage( if incoming.Wantlist() != nil { for _, key := range incoming.Wantlist() { - if bs.strategist.ShouldSendToPeer(key, sender) { + if bs.strategy.ShouldSendBlockToPeer(key, sender) { block, errBlockNotFound := bs.blockstore.Get(key) if errBlockNotFound != nil { // TODO(brian): log/return the error diff --git a/bitswap/strategy/interface.go b/bitswap/strategy/interface.go index e9fc86579c0..f034de0ad87 100644 --- a/bitswap/strategy/interface.go +++ b/bitswap/strategy/interface.go @@ -6,17 +6,17 @@ import ( u "github.com/jbenet/go-ipfs/util" ) -type Strategist interface { +type Strategy interface { Accountant // Returns a slice of Peers that Peers() []*peer.Peer // WantList returns the WantList for the given Peer - IsWantedByPeer(u.Key, *peer.Peer) bool + BlockIsWantedByPeer(u.Key, *peer.Peer) bool // ShouldSendTo(Peer) decides whether to send data to this Peer - ShouldSendToPeer(u.Key, *peer.Peer) bool + ShouldSendBlockToPeer(u.Key, *peer.Peer) bool // Seed initializes the decider to a deterministic state Seed(int64) diff --git a/bitswap/strategy/strategy.go b/bitswap/strategy/strategy.go index 8d6946dc177..4e9a6df3170 100644 --- a/bitswap/strategy/strategy.go +++ b/bitswap/strategy/strategy.go @@ -9,7 +9,7 @@ import ( ) // TODO declare thread-safe datastore -func New() Strategist { +func New() Strategy { return &strategist{ ledgerMap: ledgerMap{}, strategyFunc: yesManStrategy, @@ -36,12 +36,12 @@ func (s *strategist) Peers() []*peer.Peer { return response } -func (s *strategist) IsWantedByPeer(k u.Key, p *peer.Peer) bool { +func (s *strategist) BlockIsWantedByPeer(k u.Key, p *peer.Peer) bool { ledger := s.ledger(p) return ledger.WantListContains(k) } -func (s *strategist) ShouldSendToPeer(k u.Key, p *peer.Peer) bool { +func (s *strategist) ShouldSendBlockToPeer(k u.Key, p *peer.Peer) bool { ledger := s.ledger(p) return ledger.ShouldSend() } From a59267cc6828eea0b4c8a2f912b5b688899dd5cf Mon Sep 17 00:00:00 2001 From: Brian Tiger Chow Date: Thu, 18 Sep 2014 15:03:10 -0700 Subject: [PATCH 4/7] style(bitswap) remove unnecessary interface --- bitswap/strategy/interface.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/bitswap/strategy/interface.go b/bitswap/strategy/interface.go index f034de0ad87..bfbfe599c4b 100644 --- a/bitswap/strategy/interface.go +++ b/bitswap/strategy/interface.go @@ -7,8 +7,6 @@ import ( ) type Strategy interface { - Accountant - // Returns a slice of Peers that Peers() []*peer.Peer @@ -20,9 +18,7 @@ type Strategy interface { // Seed initializes the decider to a deterministic state Seed(int64) -} -type Accountant interface { // MessageReceived records receipt of message for accounting purposes MessageReceived(*peer.Peer, bsmsg.BitSwapMessage) error From 454af2f71dfc6deb6d3c440930157fc50402d895 Mon Sep 17 00:00:00 2001 From: Brian Tiger Chow Date: Thu, 18 Sep 2014 17:09:22 -0700 Subject: [PATCH 5/7] refactor(exchange) bitswap -> exchange/bitswap Move go-ipfs/bitswap package to go-ipfs/exchange/bitswap * Delineates the difference between the generic exchange interface and implementations (eg. BitSwap protocol) Thus, the bitswap protocol can be refined without having to overthink how future exchanges will work. Aspects common to BitSwap and other exchanges can be extracted out to the exchange package in piecemeal. Future exchange implementations can be placed in sibling packages next to exchange/bitswap. (eg. exchange/multilateral) --- blockservice/blockservice.go | 6 +++--- core/core.go | 7 ++++--- {bitswap => exchange/bitswap}/bitswap.go | 13 +++++++------ {bitswap => exchange/bitswap}/message/Makefile | 0 {bitswap => exchange/bitswap}/message/message.go | 0 {bitswap => exchange/bitswap}/message/message.pb.go | 0 {bitswap => exchange/bitswap}/message/message.proto | 0 .../bitswap}/message/message_test.go | 0 {bitswap => exchange/bitswap}/network/forwarder.go | 2 +- .../bitswap}/network/forwarder_test.go | 0 {bitswap => exchange/bitswap}/network/interface.go | 2 +- .../bitswap}/network/network_adapter.go | 2 +- .../bitswap}/notifications/notifications.go | 0 .../bitswap}/notifications/notifications_test.go | 0 {bitswap => exchange/bitswap}/offline.go | 3 ++- {bitswap => exchange/bitswap}/offline_test.go | 0 {bitswap => exchange/bitswap}/strategy/interface.go | 2 +- {bitswap => exchange/bitswap}/strategy/ledger.go | 0 .../bitswap}/strategy/ledger_test.go | 0 {bitswap => exchange/bitswap}/strategy/math.go | 0 {bitswap => exchange/bitswap}/strategy/math_test.go | 0 {bitswap => exchange/bitswap}/strategy/strategy.go | 2 +- .../bitswap}/strategy/strategy_test.go | 0 {bitswap => exchange}/interface.go | 0 24 files changed, 21 insertions(+), 18 deletions(-) rename {bitswap => exchange/bitswap}/bitswap.go (92%) rename {bitswap => exchange/bitswap}/message/Makefile (100%) rename {bitswap => exchange/bitswap}/message/message.go (100%) rename {bitswap => exchange/bitswap}/message/message.pb.go (100%) rename {bitswap => exchange/bitswap}/message/message.proto (100%) rename {bitswap => exchange/bitswap}/message/message_test.go (100%) rename {bitswap => exchange/bitswap}/network/forwarder.go (92%) rename {bitswap => exchange/bitswap}/network/forwarder_test.go (100%) rename {bitswap => exchange/bitswap}/network/interface.go (95%) rename {bitswap => exchange/bitswap}/network/network_adapter.go (97%) rename {bitswap => exchange/bitswap}/notifications/notifications.go (100%) rename {bitswap => exchange/bitswap}/notifications/notifications_test.go (100%) rename {bitswap => exchange/bitswap}/offline.go (88%) rename {bitswap => exchange/bitswap}/offline_test.go (100%) rename {bitswap => exchange/bitswap}/strategy/interface.go (94%) rename {bitswap => exchange/bitswap}/strategy/ledger.go (100%) rename {bitswap => exchange/bitswap}/strategy/ledger_test.go (100%) rename {bitswap => exchange/bitswap}/strategy/math.go (100%) rename {bitswap => exchange/bitswap}/strategy/math_test.go (100%) rename {bitswap => exchange/bitswap}/strategy/strategy.go (97%) rename {bitswap => exchange/bitswap}/strategy/strategy_test.go (100%) rename {bitswap => exchange}/interface.go (100%) diff --git a/blockservice/blockservice.go b/blockservice/blockservice.go index 0b4f15b9878..011ad0283f2 100644 --- a/blockservice/blockservice.go +++ b/blockservice/blockservice.go @@ -5,8 +5,8 @@ import ( "time" ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/datastore.go" - bitswap "github.com/jbenet/go-ipfs/bitswap" blocks "github.com/jbenet/go-ipfs/blocks" + exchange "github.com/jbenet/go-ipfs/exchange" u "github.com/jbenet/go-ipfs/util" mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash" @@ -16,11 +16,11 @@ import ( // It uses an internal `datastore.Datastore` instance to store values. type BlockService struct { Datastore ds.Datastore - Remote bitswap.Exchange + Remote exchange.Exchange } // NewBlockService creates a BlockService with given datastore instance. -func NewBlockService(d ds.Datastore, rem bitswap.Exchange) (*BlockService, error) { +func NewBlockService(d ds.Datastore, rem exchange.Exchange) (*BlockService, error) { if d == nil { return nil, fmt.Errorf("BlockService requires valid datastore") } diff --git a/core/core.go b/core/core.go index 6712f6f8386..7f106376f50 100644 --- a/core/core.go +++ b/core/core.go @@ -10,10 +10,11 @@ import ( b58 "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58" ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" - bitswap "github.com/jbenet/go-ipfs/bitswap" bserv "github.com/jbenet/go-ipfs/blockservice" config "github.com/jbenet/go-ipfs/config" ci "github.com/jbenet/go-ipfs/crypto" + exchange "github.com/jbenet/go-ipfs/exchange" + bitswap "github.com/jbenet/go-ipfs/exchange/bitswap" merkledag "github.com/jbenet/go-ipfs/merkledag" inet "github.com/jbenet/go-ipfs/net" mux "github.com/jbenet/go-ipfs/net/mux" @@ -47,7 +48,7 @@ type IpfsNode struct { Routing routing.IpfsRouting // the block exchange + strategy (bitswap) - BitSwap bitswap.Exchange + BitSwap exchange.Exchange // the block service, get/add blocks. Blocks *bserv.BlockService @@ -88,7 +89,7 @@ func NewIpfsNode(cfg *config.Config, online bool) (*IpfsNode, error) { net inet.Network // TODO: refactor so we can use IpfsRouting interface instead of being DHT-specific route *dht.IpfsDHT - exchangeSession bitswap.Exchange + exchangeSession exchange.Exchange ) if online { diff --git a/bitswap/bitswap.go b/exchange/bitswap/bitswap.go similarity index 92% rename from bitswap/bitswap.go rename to exchange/bitswap/bitswap.go index ebbdd7b1101..71b879f98bd 100644 --- a/bitswap/bitswap.go +++ b/exchange/bitswap/bitswap.go @@ -7,12 +7,13 @@ import ( context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/datastore.go" - bsmsg "github.com/jbenet/go-ipfs/bitswap/message" - bsnet "github.com/jbenet/go-ipfs/bitswap/network" - notifications "github.com/jbenet/go-ipfs/bitswap/notifications" - strategy "github.com/jbenet/go-ipfs/bitswap/strategy" blocks "github.com/jbenet/go-ipfs/blocks" blockstore "github.com/jbenet/go-ipfs/blockstore" + exchange "github.com/jbenet/go-ipfs/exchange" + bsmsg "github.com/jbenet/go-ipfs/exchange/bitswap/message" + bsnet "github.com/jbenet/go-ipfs/exchange/bitswap/network" + notifications "github.com/jbenet/go-ipfs/exchange/bitswap/notifications" + strategy "github.com/jbenet/go-ipfs/exchange/bitswap/strategy" peer "github.com/jbenet/go-ipfs/peer" u "github.com/jbenet/go-ipfs/util" ) @@ -37,7 +38,7 @@ type bitswap struct { blockstore blockstore.Blockstore // routing interface for communication - routing Directory + routing exchange.Directory notifications notifications.PubSub @@ -48,7 +49,7 @@ type bitswap struct { } // NewSession initializes a bitswap session. -func NewSession(parent context.Context, s bsnet.NetworkService, p *peer.Peer, d ds.Datastore, directory Directory) Exchange { +func NewSession(parent context.Context, s bsnet.NetworkService, p *peer.Peer, d ds.Datastore, directory exchange.Directory) exchange.Exchange { // FIXME(brian): instantiate a concrete Strategist receiver := bsnet.Forwarder{} diff --git a/bitswap/message/Makefile b/exchange/bitswap/message/Makefile similarity index 100% rename from bitswap/message/Makefile rename to exchange/bitswap/message/Makefile diff --git a/bitswap/message/message.go b/exchange/bitswap/message/message.go similarity index 100% rename from bitswap/message/message.go rename to exchange/bitswap/message/message.go diff --git a/bitswap/message/message.pb.go b/exchange/bitswap/message/message.pb.go similarity index 100% rename from bitswap/message/message.pb.go rename to exchange/bitswap/message/message.pb.go diff --git a/bitswap/message/message.proto b/exchange/bitswap/message/message.proto similarity index 100% rename from bitswap/message/message.proto rename to exchange/bitswap/message/message.proto diff --git a/bitswap/message/message_test.go b/exchange/bitswap/message/message_test.go similarity index 100% rename from bitswap/message/message_test.go rename to exchange/bitswap/message/message_test.go diff --git a/bitswap/network/forwarder.go b/exchange/bitswap/network/forwarder.go similarity index 92% rename from bitswap/network/forwarder.go rename to exchange/bitswap/network/forwarder.go index f4eba0c1459..603cd0123bc 100644 --- a/bitswap/network/forwarder.go +++ b/exchange/bitswap/network/forwarder.go @@ -2,7 +2,7 @@ package network import ( context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" - bsmsg "github.com/jbenet/go-ipfs/bitswap/message" + bsmsg "github.com/jbenet/go-ipfs/exchange/bitswap/message" peer "github.com/jbenet/go-ipfs/peer" ) diff --git a/bitswap/network/forwarder_test.go b/exchange/bitswap/network/forwarder_test.go similarity index 100% rename from bitswap/network/forwarder_test.go rename to exchange/bitswap/network/forwarder_test.go diff --git a/bitswap/network/interface.go b/exchange/bitswap/network/interface.go similarity index 95% rename from bitswap/network/interface.go rename to exchange/bitswap/network/interface.go index 89157b7a871..7033983540b 100644 --- a/bitswap/network/interface.go +++ b/exchange/bitswap/network/interface.go @@ -4,7 +4,7 @@ import ( context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" netservice "github.com/jbenet/go-ipfs/net/service" - bsmsg "github.com/jbenet/go-ipfs/bitswap/message" + bsmsg "github.com/jbenet/go-ipfs/exchange/bitswap/message" netmsg "github.com/jbenet/go-ipfs/net/message" peer "github.com/jbenet/go-ipfs/peer" ) diff --git a/bitswap/network/network_adapter.go b/exchange/bitswap/network/network_adapter.go similarity index 97% rename from bitswap/network/network_adapter.go rename to exchange/bitswap/network/network_adapter.go index f4b0a19371e..8914101bc5e 100644 --- a/bitswap/network/network_adapter.go +++ b/exchange/bitswap/network/network_adapter.go @@ -5,7 +5,7 @@ import ( context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" - bsmsg "github.com/jbenet/go-ipfs/bitswap/message" + bsmsg "github.com/jbenet/go-ipfs/exchange/bitswap/message" netmsg "github.com/jbenet/go-ipfs/net/message" peer "github.com/jbenet/go-ipfs/peer" ) diff --git a/bitswap/notifications/notifications.go b/exchange/bitswap/notifications/notifications.go similarity index 100% rename from bitswap/notifications/notifications.go rename to exchange/bitswap/notifications/notifications.go diff --git a/bitswap/notifications/notifications_test.go b/exchange/bitswap/notifications/notifications_test.go similarity index 100% rename from bitswap/notifications/notifications_test.go rename to exchange/bitswap/notifications/notifications_test.go diff --git a/bitswap/offline.go b/exchange/bitswap/offline.go similarity index 88% rename from bitswap/offline.go rename to exchange/bitswap/offline.go index d1c0fea148c..46b71d27b51 100644 --- a/bitswap/offline.go +++ b/exchange/bitswap/offline.go @@ -5,10 +5,11 @@ import ( "time" blocks "github.com/jbenet/go-ipfs/blocks" + exchange "github.com/jbenet/go-ipfs/exchange" u "github.com/jbenet/go-ipfs/util" ) -func NewOfflineExchange() Exchange { +func NewOfflineExchange() exchange.Exchange { return &offlineExchange{} } diff --git a/bitswap/offline_test.go b/exchange/bitswap/offline_test.go similarity index 100% rename from bitswap/offline_test.go rename to exchange/bitswap/offline_test.go diff --git a/bitswap/strategy/interface.go b/exchange/bitswap/strategy/interface.go similarity index 94% rename from bitswap/strategy/interface.go rename to exchange/bitswap/strategy/interface.go index bfbfe599c4b..8608c52cecc 100644 --- a/bitswap/strategy/interface.go +++ b/exchange/bitswap/strategy/interface.go @@ -1,7 +1,7 @@ package strategy import ( - bsmsg "github.com/jbenet/go-ipfs/bitswap/message" + bsmsg "github.com/jbenet/go-ipfs/exchange/bitswap/message" peer "github.com/jbenet/go-ipfs/peer" u "github.com/jbenet/go-ipfs/util" ) diff --git a/bitswap/strategy/ledger.go b/exchange/bitswap/strategy/ledger.go similarity index 100% rename from bitswap/strategy/ledger.go rename to exchange/bitswap/strategy/ledger.go diff --git a/bitswap/strategy/ledger_test.go b/exchange/bitswap/strategy/ledger_test.go similarity index 100% rename from bitswap/strategy/ledger_test.go rename to exchange/bitswap/strategy/ledger_test.go diff --git a/bitswap/strategy/math.go b/exchange/bitswap/strategy/math.go similarity index 100% rename from bitswap/strategy/math.go rename to exchange/bitswap/strategy/math.go diff --git a/bitswap/strategy/math_test.go b/exchange/bitswap/strategy/math_test.go similarity index 100% rename from bitswap/strategy/math_test.go rename to exchange/bitswap/strategy/math_test.go diff --git a/bitswap/strategy/strategy.go b/exchange/bitswap/strategy/strategy.go similarity index 97% rename from bitswap/strategy/strategy.go rename to exchange/bitswap/strategy/strategy.go index 4e9a6df3170..20881156162 100644 --- a/bitswap/strategy/strategy.go +++ b/exchange/bitswap/strategy/strategy.go @@ -3,7 +3,7 @@ package strategy import ( "errors" - bsmsg "github.com/jbenet/go-ipfs/bitswap/message" + bsmsg "github.com/jbenet/go-ipfs/exchange/bitswap/message" "github.com/jbenet/go-ipfs/peer" u "github.com/jbenet/go-ipfs/util" ) diff --git a/bitswap/strategy/strategy_test.go b/exchange/bitswap/strategy/strategy_test.go similarity index 100% rename from bitswap/strategy/strategy_test.go rename to exchange/bitswap/strategy/strategy_test.go diff --git a/bitswap/interface.go b/exchange/interface.go similarity index 100% rename from bitswap/interface.go rename to exchange/interface.go From 6f4a541c2d39cf56e6f7f1774234f51a1b890365 Mon Sep 17 00:00:00 2001 From: Brian Tiger Chow Date: Thu, 18 Sep 2014 17:30:06 -0700 Subject: [PATCH 6/7] refac(exchange) rename exchange.Interface to match golang conventions examples: http://golang.org/pkg/container/heap/#Interface http://golang.org/pkg/net/#Interface http://golang.org/pkg/sort/#Interface --- blockservice/blockservice.go | 4 ++-- core/core.go | 6 +++--- exchange/bitswap/bitswap.go | 14 ++++++++++++-- exchange/bitswap/offline.go | 2 +- exchange/interface.go | 10 +++------- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/blockservice/blockservice.go b/blockservice/blockservice.go index 011ad0283f2..89136edb026 100644 --- a/blockservice/blockservice.go +++ b/blockservice/blockservice.go @@ -16,11 +16,11 @@ import ( // It uses an internal `datastore.Datastore` instance to store values. type BlockService struct { Datastore ds.Datastore - Remote exchange.Exchange + Remote exchange.Interface } // NewBlockService creates a BlockService with given datastore instance. -func NewBlockService(d ds.Datastore, rem exchange.Exchange) (*BlockService, error) { +func NewBlockService(d ds.Datastore, rem exchange.Interface) (*BlockService, error) { if d == nil { return nil, fmt.Errorf("BlockService requires valid datastore") } diff --git a/core/core.go b/core/core.go index 7f106376f50..ad56f84149b 100644 --- a/core/core.go +++ b/core/core.go @@ -48,7 +48,7 @@ type IpfsNode struct { Routing routing.IpfsRouting // the block exchange + strategy (bitswap) - BitSwap exchange.Exchange + Exchange exchange.Interface // the block service, get/add blocks. Blocks *bserv.BlockService @@ -89,7 +89,7 @@ func NewIpfsNode(cfg *config.Config, online bool) (*IpfsNode, error) { net inet.Network // TODO: refactor so we can use IpfsRouting interface instead of being DHT-specific route *dht.IpfsDHT - exchangeSession exchange.Exchange + exchangeSession exchange.Interface ) if online { @@ -141,7 +141,7 @@ func NewIpfsNode(cfg *config.Config, online bool) (*IpfsNode, error) { Blocks: bs, DAG: dag, Resolver: &path.Resolver{DAG: dag}, - BitSwap: exchangeSession, + Exchange: exchangeSession, Identity: local, Routing: route, }, nil diff --git a/exchange/bitswap/bitswap.go b/exchange/bitswap/bitswap.go index 71b879f98bd..dcf095b0282 100644 --- a/exchange/bitswap/bitswap.go +++ b/exchange/bitswap/bitswap.go @@ -18,6 +18,16 @@ import ( u "github.com/jbenet/go-ipfs/util" ) +// TODO rename -> Router? +type Routing interface { + // FindProvidersAsync returns a channel of providers for the given key + // TODO replace with timeout with context + FindProvidersAsync(u.Key, int, time.Duration) <-chan *peer.Peer + + // Provide provides the key to the network + Provide(key u.Key) error +} + // TODO(brian): ensure messages are being received // PartnerWantListMax is the bound for the number of keys we'll store per @@ -38,7 +48,7 @@ type bitswap struct { blockstore blockstore.Blockstore // routing interface for communication - routing exchange.Directory + routing Routing notifications notifications.PubSub @@ -49,7 +59,7 @@ type bitswap struct { } // NewSession initializes a bitswap session. -func NewSession(parent context.Context, s bsnet.NetworkService, p *peer.Peer, d ds.Datastore, directory exchange.Directory) exchange.Exchange { +func NewSession(parent context.Context, s bsnet.NetworkService, p *peer.Peer, d ds.Datastore, directory Routing) exchange.Interface { // FIXME(brian): instantiate a concrete Strategist receiver := bsnet.Forwarder{} diff --git a/exchange/bitswap/offline.go b/exchange/bitswap/offline.go index 46b71d27b51..a8dbd0f8e85 100644 --- a/exchange/bitswap/offline.go +++ b/exchange/bitswap/offline.go @@ -9,7 +9,7 @@ import ( u "github.com/jbenet/go-ipfs/util" ) -func NewOfflineExchange() exchange.Exchange { +func NewOfflineExchange() exchange.Interface { return &offlineExchange{} } diff --git a/exchange/interface.go b/exchange/interface.go index 73c3ba60337..75eca06bf81 100644 --- a/exchange/interface.go +++ b/exchange/interface.go @@ -4,11 +4,12 @@ import ( "time" blocks "github.com/jbenet/go-ipfs/blocks" - peer "github.com/jbenet/go-ipfs/peer" u "github.com/jbenet/go-ipfs/util" ) -type Exchange interface { +// Any type that implements exchange.Interface may be used as an IPFS block +// exchange protocol. +type Interface interface { // Block returns the block associated with a given key. // TODO(brian): pass a context instead of a timeout @@ -21,8 +22,3 @@ type Exchange interface { // whether the block was made available on the network? HasBlock(blocks.Block) error } - -type Directory interface { - FindProvidersAsync(u.Key, int, time.Duration) <-chan *peer.Peer - Provide(key u.Key) error -} From e3b9373077612b76b017648b12fc3c9691c95d15 Mon Sep 17 00:00:00 2001 From: Brian Tiger Chow Date: Thu, 18 Sep 2014 17:43:13 -0700 Subject: [PATCH 7/7] fix(bitswap) compiler errors didn't run tests after the refactor. apologies. --- exchange/bitswap/network/forwarder_test.go | 2 +- exchange/bitswap/strategy/strategy_test.go | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/exchange/bitswap/network/forwarder_test.go b/exchange/bitswap/network/forwarder_test.go index accc2c781f1..73604e110f9 100644 --- a/exchange/bitswap/network/forwarder_test.go +++ b/exchange/bitswap/network/forwarder_test.go @@ -4,7 +4,7 @@ import ( "testing" context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context" - bsmsg "github.com/jbenet/go-ipfs/bitswap/message" + bsmsg "github.com/jbenet/go-ipfs/exchange/bitswap/message" peer "github.com/jbenet/go-ipfs/peer" ) diff --git a/exchange/bitswap/strategy/strategy_test.go b/exchange/bitswap/strategy/strategy_test.go index 4adff29a0a1..dfa216849ba 100644 --- a/exchange/bitswap/strategy/strategy_test.go +++ b/exchange/bitswap/strategy/strategy_test.go @@ -3,20 +3,20 @@ package strategy import ( "testing" - message "github.com/jbenet/go-ipfs/bitswap/message" + message "github.com/jbenet/go-ipfs/exchange/bitswap/message" "github.com/jbenet/go-ipfs/peer" "github.com/jbenet/go-ipfs/util/testutil" ) type peerAndStrategist struct { *peer.Peer - Strategist + Strategy } func newPeerAndStrategist(idStr string) peerAndStrategist { return peerAndStrategist{ - Peer: &peer.Peer{ID: peer.ID(idStr)}, - Strategist: New(), + Peer: &peer.Peer{ID: peer.ID(idStr)}, + Strategy: New(), } } @@ -32,7 +32,7 @@ func TestBlockRecordedAsWantedAfterMessageReceived(t *testing.T) { chooser.MessageReceived(beggar.Peer, messageFromBeggarToChooser) // for this test, doesn't matter if you record that beggar sent - if !chooser.IsWantedByPeer(block.Key(), beggar.Peer) { + if !chooser.BlockIsWantedByPeer(block.Key(), beggar.Peer) { t.Fatal("chooser failed to record that beggar wants block") } } @@ -51,16 +51,16 @@ func TestPeerIsAddedToPeersWhenMessageReceivedOrSent(t *testing.T) { t.Fatal("Sanity Check: Peers have same Key!") } - if !peerIsPartner(seattle.Peer, sanfrancisco.Strategist) { + if !peerIsPartner(seattle.Peer, sanfrancisco.Strategy) { t.Fatal("Peer wasn't added as a Partner") } - if !peerIsPartner(sanfrancisco.Peer, seattle.Strategist) { + if !peerIsPartner(sanfrancisco.Peer, seattle.Strategy) { t.Fatal("Peer wasn't added as a Partner") } } -func peerIsPartner(p *peer.Peer, s Strategist) bool { +func peerIsPartner(p *peer.Peer, s Strategy) bool { for _, partner := range s.Peers() { if partner.Key() == p.Key() { return true