-
Notifications
You must be signed in to change notification settings - Fork 48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Peer and Content Routing (DHT) #142
Changes from 1 commit
1dbf264
84add4d
f17ecfa
17c464b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,9 @@ const reject = require('async/reject') | |
const each = require('async/each') | ||
const EventEmitter = require('events').EventEmitter | ||
const debug = require('debug') | ||
const series = require('async/series') | ||
const map = require('async/map') | ||
const once = require('once') | ||
|
||
const CONSTANTS = require('./constants') | ||
const WantManager = require('./components/want-manager') | ||
|
@@ -126,6 +129,12 @@ class Bitswap { | |
`block:${block.cid.buffer.toString()}`, | ||
block | ||
) | ||
this.network.provide(block.cid, (err) => { | ||
if (err) { | ||
log.error('Failed to provide: %s', err.message) | ||
} | ||
}) | ||
|
||
this.engine.receivedBlocks([block.cid]) | ||
callback() | ||
}) | ||
|
@@ -150,26 +159,64 @@ class Bitswap { | |
* @returns {void} | ||
*/ | ||
get (cid, callback) { | ||
this.getMany([cid], (err, blocks) => { | ||
if (err) { | ||
return callback(err) | ||
} | ||
|
||
if (blocks && blocks.length > 0) { | ||
callback(null, blocks[0]) | ||
} else { | ||
// when a unwant happens | ||
callback() | ||
} | ||
}) | ||
} | ||
|
||
/** | ||
* Fetch a a list of blocks by cid. If the blocks are in the local | ||
* blockstore they are returned, otherwise the blocks are added to the wantlist and returned once another node sends them to us. | ||
* | ||
* @param {Array<CID>} cids | ||
* @param {function(Error, Blocks)} callback | ||
* @returns {void} | ||
*/ | ||
getMany (cids, callback) { | ||
callback = once(callback) | ||
const unwantListeners = {} | ||
const blockListeners = {} | ||
const cidStr = cid.buffer.toString() | ||
const unwantEvent = `unwant:${cidStr}` | ||
const blockEvent = `block:${cidStr}` | ||
|
||
log('get: %s', cidStr) | ||
const cleanupListener = () => { | ||
const unwantEvent = (c) => `unwant:${c}` | ||
const blockEvent = (c) => `block:${c}` | ||
const retrieved = [] | ||
const locals = [] | ||
const missing = [] | ||
|
||
log('getMany', cids.length) | ||
const cleanupListener = (cidStr) => { | ||
if (unwantListeners[cidStr]) { | ||
this.notifications.removeListener(unwantEvent, unwantListeners[cidStr]) | ||
this.notifications.removeListener( | ||
unwantEvent(cidStr), | ||
unwantListeners[cidStr] | ||
) | ||
delete unwantListeners[cidStr] | ||
} | ||
|
||
if (blockListeners[cidStr]) { | ||
this.notifications.removeListener(blockEvent, blockListeners[cidStr]) | ||
this.notifications.removeListener( | ||
blockEvent(cidStr), | ||
blockListeners[cidStr] | ||
) | ||
delete blockListeners[cidStr] | ||
} | ||
} | ||
|
||
const addListener = () => { | ||
const addListeners = (cids) => { | ||
cids.forEach((c) => addListener(c)) | ||
} | ||
|
||
const addListener = (cid) => { | ||
const cidStr = cid.buffer.toString() | ||
|
||
unwantListeners[cidStr] = () => { | ||
log(`manual unwant: ${cidStr}`) | ||
cleanupListener() | ||
|
@@ -180,26 +227,61 @@ class Bitswap { | |
blockListeners[cidStr] = (block) => { | ||
this.wm.cancelWants([cid]) | ||
cleanupListener(cid) | ||
callback(null, block) | ||
retrieved.push(block) | ||
|
||
if (retrieved.length === missing.length) { | ||
finish(callback) | ||
} | ||
} | ||
|
||
this.notifications.once(unwantEvent, unwantListeners[cidStr]) | ||
this.notifications.once(blockEvent, blockListeners[cidStr]) | ||
this.notifications.once( | ||
unwantEvent(cidStr), | ||
unwantListeners[cidStr] | ||
) | ||
this.notifications.once( | ||
blockEvent(cidStr), | ||
blockListeners[cidStr] | ||
) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why would that be beneficial? We can test it more in here if we want to. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exactly to add more tests :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
this.blockstore.has(cid, (err, has) => { | ||
if (err) { | ||
return callback(err) | ||
} | ||
const finish = (cb) => { | ||
map(locals, (cid, cb) => { | ||
this.blockstore.get(cid, cb) | ||
}, (err, localBlocks) => { | ||
if (err) { | ||
return callback(err) | ||
} | ||
|
||
if (has) { | ||
log('already have block: %s', cidStr) | ||
return this.blockstore.get(cid, callback) | ||
} | ||
callback(null, localBlocks.concat(retrieved)) | ||
}) | ||
} | ||
|
||
addListener() | ||
this.wm.wantBlocks([cid]) | ||
}) | ||
series([ | ||
(cb) => each(cids, (cid, cb) => { | ||
this.blockstore.has(cid, (err, has) => { | ||
if (err) { | ||
return cb(err) | ||
} | ||
|
||
if (has) { | ||
locals.push(cid) | ||
} else { | ||
missing.push(cid) | ||
} | ||
cb() | ||
}) | ||
}, cb), | ||
(cb) => { | ||
if (missing.length > 0) { | ||
addListeners(missing) | ||
this.wm.wantBlocks(missing) | ||
|
||
this.network.findAndConnect(cids[0], CONSTANTS.maxProvidersPerRequest, cb) | ||
} else { | ||
cb() | ||
} | ||
} | ||
], finish) | ||
} | ||
|
||
// removes the given cids from the wantlist independent of any ref counts | ||
|
@@ -269,6 +351,11 @@ class Bitswap { | |
block | ||
) | ||
this.engine.receivedBlocks([block.cid]) | ||
this.network.provide(block.cid, (err) => { | ||
if (err) { | ||
log.error('Failed to provide: %s', err.message) | ||
} | ||
}) | ||
}) | ||
cb() | ||
}) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dialing without a protocol doesn't create a
conn
because it never opens a multiplex conn, it is what is called 'warming up a conn'.This can be just:
this.libp2p.dial(peerId, callback)