Connecting bitswap and blockstore

yamux
John Jones 2017-07-24 14:56:30 -05:00
parent 4368e052e2
commit 9924d5dcf7
12 changed files with 192 additions and 33 deletions

View File

@ -4,16 +4,54 @@
#include "libp2p/crypto/encoding/base32.h"
#include "ipfs/cid/cid.h"
#include "ipfs/blocks/block.h"
#include "ipfs/blocks/blockstore.h"
#include "ipfs/datastore/ds_helper.h"
#include "ipfs/repo/fsrepo/fs_repo.h"
#include "libp2p/os/utils.h"
/***
* Create a new Blockstore struct
* @param fs_repo the FSRepo to use
* @returns the new Blockstore struct, or NULL if there was a problem.
*/
struct Blockstore* ipfs_blockstore_new(const struct FSRepo* fs_repo) {
struct Blockstore* blockstore = (struct Blockstore*) malloc(sizeof(struct Blockstore));
if(blockstore != NULL) {
blockstore->blockstoreContext = (struct BlockstoreContext*) malloc(sizeof(struct BlockstoreContext));
if (blockstore->blockstoreContext == NULL) {
free(blockstore);
return NULL;
}
blockstore->blockstoreContext->fs_repo = fs_repo;
blockstore->Delete = ipfs_blockstore_delete;
blockstore->Get = ipfs_blockstore_get;
blockstore->Has = ipfs_blockstore_has;
blockstore->Put = ipfs_blockstore_put;
}
return blockstore;
}
/**
* Release resources of a Blockstore struct
* @param blockstore the struct to free
* @returns true(1)
*/
int ipfs_blockstore_free(struct Blockstore* blockstore) {
if (blockstore != NULL) {
if (blockstore->blockstoreContext != NULL)
free(blockstore->blockstoreContext);
free(blockstore);
}
return 1;
}
/**
* Delete a block based on its Cid
* @param cid the Cid to look for
* @param returns true(1) on success
*/
int ipfs_blockstore_delete(struct Cid* cid, struct FSRepo* fs_repo) {
int ipfs_blockstore_delete(const struct BlockstoreContext* context, struct Cid* cid) {
return 0;
}
@ -22,7 +60,7 @@ int ipfs_blockstore_delete(struct Cid* cid, struct FSRepo* fs_repo) {
* @param cid the Cid to look for
* @returns true(1) if found
*/
int ipfs_blockstore_has(struct Cid* cid, struct FSRepo* fs_repo) {
int ipfs_blockstore_has(const struct BlockstoreContext* context, struct Cid* cid) {
return 0;
}
@ -74,11 +112,11 @@ char* ipfs_blockstore_path_get(const struct FSRepo* fs_repo, const char* filenam
* @param block where to put the data to be returned
* @returns true(1) on success
*/
int ipfs_blockstore_get(const unsigned char* hash, size_t hash_size, struct Block** block, const struct FSRepo* fs_repo) {
int ipfs_blockstore_get(const struct BlockstoreContext* context, struct Cid* cid, struct Block** block) {
// get datastore key, which is a base32 key of the multihash
unsigned char* key = ipfs_blockstore_hash_to_base32(hash, hash_size);
unsigned char* key = ipfs_blockstore_hash_to_base32(cid->hash, cid->hash_length);
char* filename = ipfs_blockstore_path_get(fs_repo, (char*)key);
char* filename = ipfs_blockstore_path_get(context->fs_repo, (char*)key);
size_t file_size = os_utils_file_size(filename);
unsigned char buffer[file_size];
@ -89,6 +127,8 @@ int ipfs_blockstore_get(const unsigned char* hash, size_t hash_size, struct Bloc
int retVal = ipfs_blocks_block_protobuf_decode(buffer, bytes_read, block);
(*block)->cid = cid;
free(key);
free(filename);
@ -100,7 +140,7 @@ int ipfs_blockstore_get(const unsigned char* hash, size_t hash_size, struct Bloc
* @param block the block to store
* @returns true(1) on success
*/
int ipfs_blockstore_put(struct Block* block, struct FSRepo* fs_repo) {
int ipfs_blockstore_put(const struct BlockstoreContext* context, struct Block* block) {
// from blockstore.go line 118
int retVal = 0;
@ -123,7 +163,7 @@ int ipfs_blockstore_put(struct Block* block, struct FSRepo* fs_repo) {
}
// now write byte array to file
char* filename = ipfs_blockstore_path_get(fs_repo, (char*)key);
char* filename = ipfs_blockstore_path_get(context->fs_repo, (char*)key);
if (filename == NULL) {
free(key);
return 0;

View File

@ -98,7 +98,7 @@ int ipfs_cid_protobuf_decode(unsigned char* buffer, size_t buffer_length, struct
* @param cid where to put the results
* @returns true(1) on success
*/
int ipfs_cid_new(int version, unsigned char* hash, size_t hash_length, const char codec, struct Cid** ptrToCid) {
int ipfs_cid_new(int version, const unsigned char* hash, size_t hash_length, const char codec, struct Cid** ptrToCid) {
// allocate memory
*ptrToCid = (struct Cid*)malloc(sizeof(struct Cid));
struct Cid* cid = *ptrToCid;

View File

@ -40,6 +40,7 @@ int ipfs_node_online_new(const char* repo_path, struct IpfsNode** node) {
local_node->identity = fs_repo->config->identity;
local_node->peerstore = libp2p_peerstore_new(local_node->identity->peer_id);
local_node->providerstore = libp2p_providerstore_new();
local_node->blockstore = ipfs_blockstore_new(fs_repo);
local_node->mode = MODE_OFFLINE;
local_node->routing = ipfs_routing_new_online(local_node, &fs_repo->config->identity->private_key, NULL);

View File

@ -2,6 +2,7 @@
* Methods for the Bitswap exchange
*/
#include <stdlib.h>
#include "ipfs/core/ipfs_node.h"
#include "ipfs/exchange/exchange.h"
#include "ipfs/exchange/bitswap/bitswap.h"
#include "ipfs/exchange/bitswap/message.h"
@ -11,7 +12,7 @@
* @param sessionContext the context
* @returns an allocated Exchange structure
*/
struct Exchange* ipfs_bitswap_new(struct SessionContext* sessionContext) {
struct Exchange* ipfs_bitswap_exchange_start(struct SessionContext* sessionContext, struct IpfsNode* ipfs_node) {
struct Exchange* exchange = (struct Exchange*) malloc(sizeof(struct Exchange));
if (exchange != NULL) {
struct BitswapContext* bitswapContext = (struct BitswapContext*) malloc(sizeof(struct BitswapContext));
@ -21,13 +22,14 @@ struct Exchange* ipfs_bitswap_new(struct SessionContext* sessionContext) {
}
exchange->exchangeContext = (void*) bitswapContext;
bitswapContext->sessionContext = sessionContext;
//TODO: fill in the exchangeContext
bitswapContext->ipfsNode = ipfs_node;
exchange->IsOnline = ipfs_bitswap_is_online;
exchange->Close = ipfs_bitswap_close;
exchange->HasBlock = ipfs_bitswap_has_block;
exchange->GetBlock = ipfs_bitswap_get_block;
exchange->GetBlocks = ipfs_bitswap_get_blocks;
}
//TODO: Start the threads for the network
return exchange;
}
@ -39,6 +41,7 @@ struct Exchange* ipfs_bitswap_new(struct SessionContext* sessionContext) {
int ipfs_bitswap_free(struct Exchange* exchange) {
if (exchange != NULL) {
if (exchange->exchangeContext != NULL) {
ipfs_bitswap_close(exchange->exchangeContext);
free(exchange->exchangeContext);
}
free(exchange);
@ -88,7 +91,13 @@ int ipfs_bitswap_has_block(void* exchangeContext, struct Block* block) {
* taking in a pointer to a callback, as this could take a while (or fail).
*/
int ipfs_bitswap_get_block(void* exchangeContext, struct Cid* cid, struct Block** block) {
// TODO: Implement this method
struct BitswapContext* bitswapContext = (struct BitswapContext*)exchangeContext;
if (bitswapContext != NULL) {
// check locally first
if (bitswapContext->ipfsNode->blockstore->Get(bitswapContext->ipfsNode->blockstore->blockstoreContext, cid, block))
return 1;
// now ask the network
}
return 0;
}
@ -99,16 +108,3 @@ int ipfs_bitswap_get_blocks(void* exchangeContext, struct Libp2pVector* Cids, st
// TODO: Implement this method
return 0;
}
/***
* Receive a BitswapMessage from a peer.
* @param exchangeContext the context
* @param peer_id the origin
* @param peer_id_size the size of the peer_id
* @param message the message
* @returns true(1) on success, otherwise false(0)
*/
int ipfs_bitswap_receive_message(void* exchangeContext, unsigned char* peer_id, int peer_id_size, struct BitswapMessage* message) {
return 0;
}

View File

@ -1,8 +1,21 @@
/***
* This implements the BitswapNetwork. Members of this network can fill requests and
* smartly handle queues of local and remote requests.
*
* For a somewhat accurate diagram of how this may work, @see https://github.com/ipfs/js-ipfs-bitswap
*/
#include "ipfs/exchange/bitswap/network.h"
/***
* The main loop
*/
/**
* We received a BitswapMessage from the network
*/
/**
* We want to pop something off the queue to send to a peer.
* This can be a wantlist or blocks
*/

View File

@ -8,34 +8,63 @@
#include "ipfs/cid/cid.h"
#include "ipfs/repo/fsrepo/fs_repo.h"
struct BlockstoreContext {
const struct FSRepo* fs_repo;
};
struct Blockstore {
struct BlockstoreContext* blockstoreContext;
int (*Delete)(const struct BlockstoreContext* context, struct Cid* cid);
int (*Has)(const struct BlockstoreContext* context, struct Cid* cid);
int (*Get)(const struct BlockstoreContext* context, struct Cid* cid, struct Block** block);
int (*Put)(const struct BlockstoreContext* context, struct Block* block);
};
/***
* Create a new Blockstore struct
* @param fs_repo the FSRepo to use
* @returns the new Blockstore struct, or NULL if there was a problem.
*/
struct Blockstore* ipfs_blockstore_new(const struct FSRepo* fs_repo);
/**
* Release resources of a Blockstore struct
* @param blockstore the struct to free
* @returns true(1)
*/
int ipfs_blockstore_free(struct Blockstore* blockstore);
/**
* Delete a block based on its Cid
* @param context the context
* @param cid the Cid to look for
* @param returns true(1) on success
*/
int ipfs_blockstore_delete(struct Cid* cid, struct FSRepo* fs_repo);
int ipfs_blockstore_delete(const struct BlockstoreContext* context, struct Cid* cid);
/***
* Determine if the Cid can be found
* @param context the context
* @param cid the Cid to look for
* @returns true(1) if found
*/
int ipfs_blockstore_has(struct Cid* cid, struct FSRepo* fs_repo);
int ipfs_blockstore_has(const struct BlockstoreContext* context, struct Cid* cid);
/***
* Find a block based on its Cid
* @param context the context
* @param cid the Cid to look for
* @param block where to put the data to be returned
* @returns true(1) on success
*/
int ipfs_blockstore_get(const unsigned char* hash, size_t hash_length, struct Block** block, const struct FSRepo* fs_repo);
int ipfs_blockstore_get(const struct BlockstoreContext* context, struct Cid* cid, struct Block** block);
/***
* Put a block in the blockstore
* @param block the block to store
* @returns true(1) on success
*/
int ipfs_blockstore_put(struct Block* block, const struct FSRepo* fs_repo);
int ipfs_blockstore_put(const struct BlockstoreContext* context, struct Block* block);
/***
* Put a struct UnixFS in the blockstore

View File

@ -72,7 +72,7 @@ size_t ipfs_cid_protobuf_encode_size(struct Cid* incoming);
* @param cid where to put the results
* @returns true(1) on success
*/
int ipfs_cid_new(int version, unsigned char* hash, size_t hash_length, const char codec, struct Cid** cid);
int ipfs_cid_new(int version, const unsigned char* hash, size_t hash_length, const char codec, struct Cid** cid);
/***
* Free the resources from a Cid

View File

@ -1,5 +1,6 @@
#pragma once
#include "ipfs/blocks/blockstore.h"
#include "ipfs/repo/config/identity.h"
#include "ipfs/repo/fsrepo/fs_repo.h"
#include "ipfs/routing/routing.h"
@ -15,6 +16,7 @@ struct IpfsNode {
struct Peerstore* peerstore;
struct ProviderStore* providerstore;
struct IpfsRouting* routing;
struct Blockstore* blockstore;
//struct Pinner pinning; // an interface
//struct Mount** mounts;
// TODO: Add more here

View File

@ -1,13 +1,68 @@
/***
* Bitswap implements the exchange "interface"
* @see ../exchange.h
*/
#include "ipfs/core/ipfs_node.h"
#include "ipfs/exchange/exchange.h"
struct BitswapContext {
struct SessionContext* sessionContext;
struct IpfsNode* ipfsNode;
};
/**
* Start up the bitswap exchange
* @param sessionContext the context
* @returns an Exchange struct that refers to the exchange
*/
struct Exchange* ipfs_bitswap_exchange_start(struct SessionContext* sessionContext, struct IpfsNode* ipfsNode);
/***
* These are the implementation methods for the exchange "Interface"
*/
/***
* Checks to see if the Bitswap service is online
* @param exhcnageContext a pointer to a BitswapContext
* @reutrns true(1) if online, false(0) otherwise.
*/
int ipfs_bitswap_is_online(void* exchangeContext);
/***
* Closes down the Bitswap network
* @param exchangeContext a pointer to a BitswapContext
* @returns true(1)
*/
int ipfs_bitswap_close(void* exchangeContext);
/****
* Notify the BitswapNetwork that we have this block
* @param exchangeContext a pointer to a BitswapContext
* @block the block that we have
* @reutrns true(1) if successful, false(0) if not.
*/
int ipfs_bitswap_has_block(void* exchangeContext, struct Block* block);
/**
* Retrieve a block from the BitswapNetwork
* Note: This may pull the file from the local blockstore.
* Note: If false(0) is returned, block will be NULL
*
* @param exchangeContext a pointer to a BitswapContext
* @param cid the Cid of the block we're looking for
* @param block a pointer to the block when we find it.
* @returns true(1) on success, false(0) otherwise.
*/
int ipfs_bitswap_get_block(void* exchangeContext, struct Cid* cid, struct Block** block);
int ipfs_bitswap_get_blocks(void* exchangeContext, struct Libp2pVector* Cids, struct Libp2pVector** blocks);
/***
* Retrieve a collection of blocks from the BitswapNetwork
* Note: The return of false(0) means that not all blocks were found.
*
* @param exchangeContext a pointer to a BitswapContext
* @param cids a collection of Cid structs
* @param blocks a collection that contains the results.
* @param true(1) on success, false(0) otherwise
*/
int ipfs_bitswap_get_blocks(void* exchangeContext, struct Libp2pVector* cids, struct Libp2pVector** blocks);

View File

@ -1,3 +1,4 @@
#pragma once
/**
* This is the definition of an "Exchange"
*
@ -8,10 +9,19 @@
#include "ipfs/cid/cid.h"
#include "libp2p/utils/vector.h"
/**
* These are methods that the local IPFS daemon (or client)
* call to communicate with the local repository or network
*/
struct Exchange {
/**
* Retrieve a block from peers within the deadline enforced
* by the context
*
* NOTE: Shouldn't the block parameter be a callback (function pointer)?
* Otherwise, this function is going to block. Is that what we want?
*
* @param context the context
* @param cid the hash of the block to retrieve
* @param block a pointer to the block (allocated by this method if return is true)

View File

@ -698,7 +698,11 @@ int ipfs_repo_fsrepo_block_write(struct Block* block, const struct FSRepo* fs_re
* and the base32 encoded multihash as the value.
*/
int retVal = 1;
retVal = ipfs_blockstore_put(block, fs_repo);
struct Blockstore* blockstore = ipfs_blockstore_new(fs_repo);
if (blockstore == NULL)
return 0;
retVal = ipfs_blockstore_put(blockstore->blockstoreContext, block);
ipfs_blockstore_free(blockstore);
if (retVal == 0)
return 0;
// take the cid, base32 it, and send both to the datastore
@ -799,7 +803,17 @@ int ipfs_repo_fsrepo_block_read(const unsigned char* hash, size_t hash_length, s
if (retVal == 0) // maybe it doesn't exist?
return 0;
// now get the block from the blockstore
retVal = ipfs_blockstore_get(hash, hash_length, block, fs_repo);
struct Cid* cid = NULL;
if (!ipfs_cid_new(0, hash, hash_length, CID_PROTOBUF, &cid))
return 0;
struct Blockstore* blockstore = ipfs_blockstore_new(fs_repo);
if (blockstore == NULL) {
ipfs_cid_free(cid);
return 0;
}
retVal = ipfs_blockstore_get(blockstore->blockstoreContext, cid, block);
ipfs_blockstore_free(blockstore);
ipfs_cid_free(cid);
return retVal;
}

View File

@ -103,6 +103,5 @@ int test_bitswap_protobuf() {
message->wantlist->full = 1;
retVal = 1;
exit:
return retVal;
}