{"action":"created","issue":{"url":"https://api.github.com/repos/ipfs/specs/issues/57","labels_url":"https://api.github.com/repos/ipfs/specs/issues/57/labels{/name}","comments_url":"https://api.github.com/repos/ipfs/specs/issues/57/comments","events_url":"https://api.github.com/repos/ipfs/specs/issues/57/events","html_url":"https://github.com/ipfs/specs/pull/57","id":124605461,"number":57,"title":"WIP: Data Importing Spec","user":{"login":"diasdavid","id":1211152,"avatar_url":"https://avatars.githubusercontent.com/u/1211152?v=3","gravatar_id":"","url":"https://api.github.com/users/diasdavid","html_url":"https://github.com/diasdavid","followers_url":"https://api.github.com/users/diasdavid/followers","following_url":"https://api.github.com/users/diasdavid/following{/other_user}","gists_url":"https://api.github.com/users/diasdavid/gists{/gist_id}","starred_url":"https://api.github.com/users/diasdavid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/diasdavid/subscriptions","organizations_url":"https://api.github.com/users/diasdavid/orgs","repos_url":"https://api.github.com/users/diasdavid/repos","events_url":"https://api.github.com/users/diasdavid/events{/privacy}","received_events_url":"https://api.github.com/users/diasdavid/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/ipfs/specs/labels/in%20progress","name":"in progress","color":"ededed"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-01-02T19:00:40Z","updated_at":"2016-01-03T13:34:41Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/ipfs/specs/pulls/57","html_url":"https://github.com/ipfs/specs/pull/57","diff_url":"https://github.com/ipfs/specs/pull/57.diff","patch_url":"https://github.com/ipfs/specs/pull/57.patch"},"body":"@whyrusleeping let's fill the implementations chapter with pointers to where the current chunker and layout is implemented and go and align on what the interfaces should be for this importers"},"comment":{"url":"https://api.github.com/repos/ipfs/specs/issues/comments/168499368","html_url":"https://github.com/ipfs/specs/pull/57#issuecomment-168499368","issue_url":"https://api.github.com/repos/ipfs/specs/issues/57","id":168499368,"user":{"login":"whyrusleeping","id":1243164,"avatar_url":"https://avatars.githubusercontent.com/u/1243164?v=3","gravatar_id":"","url":"https://api.github.com/users/whyrusleeping","html_url":"https://github.com/whyrusleeping","followers_url":"https://api.github.com/users/whyrusleeping/followers","following_url":"https://api.github.com/users/whyrusleeping/following{/other_user}","gists_url":"https://api.github.com/users/whyrusleeping/gists{/gist_id}","starred_url":"https://api.github.com/users/whyrusleeping/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/whyrusleeping/subscriptions","organizations_url":"https://api.github.com/users/whyrusleeping/orgs","repos_url":"https://api.github.com/users/whyrusleeping/repos","events_url":"https://api.github.com/users/whyrusleeping/events{/privacy}","received_events_url":"https://api.github.com/users/whyrusleeping/received_events","type":"User","site_admin":false},"created_at":"2016-01-03T13:34:41Z","updated_at":"2016-01-03T13:34:41Z","body":"For importers, we have the default chunker that splits the input stream into blocks of 256k, and one that does rabin fingerprints for the chunking. The interface for our chunker looks like:\r\n```\r\ntype Chunker interface {\r\n    NextBytes() ([]byte, error)\r\n}\r\n```\r\n\r\n`NextBytes()`gets called on the chunker until no bytes are remaining, at which point it returns an `EOF` sentinel error (implementation details).\r\n\r\nThe second part of our importing code is the layout engine, we have two of those as well. The default is the balanced tree. [The tree has a width at each layer of  256k/sizeof(link)](https://github.com/ipfs/go-ipfs/blob/master/importer/helpers/helpers.go#L34)\r\n\r\nThe general algorithm for building the balanced tree is this:\r\n\r\nif only one block exists, it is its own depth=1 tree. From depth 1 trees, we can generate depth=2 trees by generating up to MAXWIDTH depth=1 trees and adding them as children of a new node. Using the same recursive logic, we can generate any depth of tree dynamically as more and more data comes in from the chunker (eliminating the need to know data size beforehand to select a depth). Note, data is ONLY stored in the leaf nodes, storing data in intermediate nodes is complicated and fragile and not conducive to effective deduplication (although some significant latency gains might be made by doing so).\r\n\r\nThe second layout algorithm is called the trickledag and is something i wrote to provide a data format better suited to sequential streaming of content. The basic idea is that a depth N tree has X leaf nodes as children, and Y trees of each depth up to N-1. Its essentially an expanded binomial heap construction. The advantage is that at each point in traversing the tree (at least sequentially) you can make a single request and get real data. That code is here: https://github.com/ipfs/go-ipfs/blob/master/importer/trickle/trickledag.go"}}