Skip to content
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

[WIP] Filestore Implementation #2634

Closed
wants to merge 209 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
209 commits
Select commit Hold shift + click to select a range
929b49f
In the measure package don't return ErrInvalidType in batch Put.
kevina Apr 21, 2016
d8c1ccf
New "multi" datastore.
kevina Apr 22, 2016
a4ffdaf
Create a new AdvReader interface.
kevina Jun 1, 2016
f4ad3ba
Basic implementation of "add --no-copy".
kevina May 6, 2016
28d18ce
Add basic tests for "add --no-copy".
kevina Apr 22, 2016
0f3f2e9
When reconstructing block always verify the result.
kevina Apr 23, 2016
7f1bf41
Add Basic Query and "Direct" commands to filestore. Needs Testing.
kevina Apr 24, 2016
cc30fa6
Save ref to Filestore in repo for future direct access.
kevina Apr 24, 2016
be4649b
Add Self() method to be able to get to FSRepo.
kevina Apr 25, 2016
7853241
Add "filestore" commands to list contents and verify filestore.
kevina Apr 25, 2016
4fc46db
Disable failing test.
kevina Apr 27, 2016
725fb99
Refactor.
kevina Apr 27, 2016
5e1897f
Add temp. utility command to find dangling pins.
kevina Apr 27, 2016
cc65b61
Add "filestore rm" command.
kevina Apr 27, 2016
4a2807f
"filestore ls": add "--quiet" option
kevina Apr 27, 2016
a7a2e55
"filestore verify": change "invalid" status to "changed".
kevina Apr 27, 2016
889f470
Check if the WholeFile flag should be set for leaf nodes in filestore…
kevina Apr 27, 2016
d028645
Add "filestore rm-invalid" command.
kevina Apr 27, 2016
958e344
"filestore ls": add help text and rework output
kevina Apr 28, 2016
07a292c
"filestore verify": only verify leaf nodes, add help text
kevina Apr 29, 2016
b0a6468
Add sharness tests for new "filestore" commands.
kevina Apr 29, 2016
a2610b2
Report an error when trying to use "--no-copy" when daemon is online.
kevina Apr 30, 2016
1203021
Fix bug in LevelDB datastore's Delete() method.
kevina May 1, 2016
b5a89f1
In the filestore, reconstruct the block directly when retrieving.
kevina May 1, 2016
caf89fb
Refactor filestore utility commands.
kevina Apr 30, 2016
5e20d47
Enhance "filestore rm" to give better output.
kevina May 2, 2016
92170c9
Filestore: Change DataObj struct to use bit flags.
kevina May 2, 2016
8f136fd
Filestore: Only verify contents of block if the file's mod-time has c…
kevina May 2, 2016
c7f9757
Filestore: Get the modification time from the file before it is first…
kevina May 2, 2016
e649788
Move filestore utility commands into their own package.
kevina May 4, 2016
85cae36
Redo "filestore verify" to check more than if blocks can be read.
kevina May 4, 2016
ebca489
New command "filestore clean", replaces obsolete "... rm-invalid" com…
kevina May 5, 2016
d9f3844
Add "filestore fix-pins", remove obsolete "filestore find-dangling-pi…
kevina May 7, 2016
38eb47c
New command: "filestore repin".
kevina May 7, 2016
43bb5f4
Tweak help text for filestore commands.
kevina May 7, 2016
1f2fda7
Filestore: Refactor
kevina May 8, 2016
9022879
Rewrite "filestore rm" for greater functionality and to correctly han…
kevina May 8, 2016
f08ea6b
Change "repin" to "unpinned" and just list the unpinned objects.
kevina May 8, 2016
6f97efd
"filestore rm": Avoid checking for indirect pins when "--force" is used.
kevina May 8, 2016
7db64c4
New command "filestore rm-dups"
kevina May 8, 2016
ee9d941
Filestore: Todo list.
kevina May 8, 2016
70f4453
Enhance filestore testcases.
kevina May 9, 2016
53f499f
"filestore repin": Add --skip-root option.
kevina May 10, 2016
df10f8e
Filestore: Add README.
kevina May 10, 2016
906320f
Fix a compile error in a test case.
kevina May 11, 2016
f9896fa
Do not use separate absolute Path, just make the FullPath absolute.
kevina May 11, 2016
c2df48e
Add way to add files on the API server's filesystem without sending t…
kevina May 12, 2016
f37c326
Filestore: Refactor test cases.
kevina May 12, 2016
7991036
Filestore: Update README and add testcase using new add-ss functionally
kevina May 12, 2016
4313c4f
Filestore: Refactor fsutil.List
kevina May 13, 2016
2b09cb4
"filestore rm": Do not delete blocks that are shared with another pin…
kevina May 14, 2016
d97b42e
New command "filestore ls-files"
kevina May 17, 2016
1ded141
Add Filestore.Verify config option to control when block are verified.
kevina May 18, 2016
9f689fa
Filestore: Remove todo list.
kevina May 18, 2016
f40117f
Gofmt
kevina May 21, 2016
ff4ee54
Filestore: Expand tests.
kevina May 21, 2016
af94888
Create an alternative blockstore for use with the filestore.
kevina May 21, 2016
3d3b544
Factor out filestore specific code from DagServices.
kevina May 22, 2016
6153f43
Keep track of offsets in the DAG builder and not the splitter.
kevina May 22, 2016
c0fe98f
Filestore: Change FileRoot constant to Internal
kevina May 22, 2016
72fb3c6
Simplify "multi" datastore. Move logic into filestore's blockstore.
kevina May 22, 2016
976635a
In the fsrepo, provide ways to get sub-datastore by name.
kevina May 23, 2016
47962cc
Gofmt and clean up diff noise.
kevina May 23, 2016
c82a9cf
New command "filestore upgrade"
kevina May 24, 2016
951df45
New command: "filestore mv"
kevina May 27, 2016
490026c
Filestore: Minor Refactor.
kevina May 27, 2016
d168f04
"filestore ls": enhance
kevina May 28, 2016
d44c892
Filestore: res.Request() => req
kevina May 28, 2016
2fe38b3
"filestore verify": add ability to specify hashes to verify
kevina May 28, 2016
fd077d3
Filestore: Prevent server crash when DataPtr.PosInfo is not set.
kevina Jun 3, 2016
293e848
Fix multi-file add so it works as expected.
kevina Jun 6, 2016
aafc61d
Filestore: Cleanup.
kevina Jun 6, 2016
b643748
Filestore: change "add --no-copy" to "filestore add"
kevina Jun 1, 2016
0cdf270
Rework "filestore add" command. Absolute paths now always required.
kevina Jun 3, 2016
30a11ce
Handle errors returned by the splitter in the DAG builder.
kevina Jun 4, 2016
d4f1638
Filestore: Add support for "porcelain" output.
kevina Jun 6, 2016
07376d8
Filestore: Add another '-v' level to "filestore verify".
kevina May 31, 2016
7ddf150
Filestore: Allow adds when server is online.
kevina Jun 4, 2016
3676047
Filestore: Don't Store Empty Files in Filestore
kevina Jun 4, 2016
4827fa7
Filestore: new func CleanPath like filepath.Clean but leaves '..' alone
kevina Jun 1, 2016
c449829
Filestore: Readd support for realtive directories with '-P' and '-l' …
kevina Jun 4, 2016
e69a33a
Filestore: Update README.
kevina Jun 4, 2016
6eb4f0d
Filestore: Add example script. Update README.
kevina Jun 6, 2016
53cb291
Filestore: Use filepath.IsAbs() not path.IsAbs().
kevina Jun 7, 2016
ea3716f
Filestore: Fix -P to work as expected on Windows.
kevina Jun 8, 2016
26416a4
Filestore: Fix add-dir.sh script
kevina Jun 9, 2016
2bf9260
Filestore: Update README
kevina Jun 9, 2016
0106446
Filestore: Make sure to explicitly close files to avoid a file handle…
kevina Jun 11, 2016
629803e
Move multi-datastore out of go-datastore.
kevina Jun 13, 2016
d3bf502
Merge remote-tracking branch 'upstream/master' into kevina/filestore
kevina Jun 13, 2016
d5ef180
Filestore: Eliminate need for DataPtr
kevina Jun 10, 2016
b454ba0
Filestore: Generalize Reconstruct() function
kevina Jun 10, 2016
7a64523
Filestore: Rewrite Optimized version of Reconstruct().
kevina Jun 13, 2016
1135469
Store PosInfo in BasicBlock, eliminate NodeToBlock hook in DAGService.
kevina Jun 13, 2016
e976430
Diff noise cleanup.
kevina Jun 13, 2016
6ff54cf
Filestore: Cleanup.
kevina Jun 14, 2016
b5c3561
Filestore: Cleanup
kevina Jun 14, 2016
382e1a6
Filestore: Simplify the specialized Blockstore
kevina Jun 14, 2016
02a6f2a
Filestore: Clean up Errors and Command Line help text.
kevina Jun 17, 2016
cdb8ea5
Filestore: More Error message cleanup.
kevina Jun 18, 2016
a9cc988
Filestore: Clean up Errors and documentation.
kevina Jun 18, 2016
36a9948
Filestore: Remove spurious ".EnableStdin()."
kevina Jun 18, 2016
09e3da1
Filestore: Use LevelDB directly.
kevina Jun 19, 2016
a861ad7
Filestore: Documentation: Change README
djdv Jul 6, 2016
f82b39e
Merge remote-tracking branch 'upstream/master' into kevina/filestore
kevina Aug 4, 2016
3c3f02c
Filestore: Enhance "filestore upgrade" to convert keys to base32.
kevina Aug 5, 2016
3ffc5f1
Merge remote-tracking branch 'upstream/master' into kevina/filestore
kevina Aug 19, 2016
270e402
Replace the multi-datastore with a multi-blockstore.
kevina Aug 16, 2016
a482ee1
Implement multiblockstore.AllKeysChan(), GC now uses the first mount.
kevina Aug 17, 2016
5a73226
Add DAGService.GetLinks() method and use it in the GC and elsewhere.
kevina Aug 19, 2016
7697929
Filestore: Don't pin by default when adding files.
kevina Aug 20, 2016
a8f0c9f
Add "block locate" command.
kevina Aug 21, 2016
8bcc429
Pinner: Providing Pinned.String() method and use it in "block rm"
kevina Aug 21, 2016
c4fefd5
Filestore: Simplify "filestore rm" removing pinning commands.
kevina Aug 21, 2016
75baf15
Filestore: Update README to reflect reality.
kevina Aug 21, 2016
33099b2
"blockstore rm": move core functionally into blockstore_util package
kevina Aug 21, 2016
f9acb13
Filestore: Use "block rm" to remove blocks.
kevina Aug 22, 2016
f68bba7
"block/filestore rm": Allow removal of pinned but duplicate blocks.
kevina Aug 22, 2016
e9ba1fb
"add": add "--allow-dup" option.
kevina Aug 22, 2016
68f7240
Filestore: kill "rm-dups" replace it by a more flexable "dups".
kevina Aug 22, 2016
9542730
Filestore: Update README.
kevina Aug 22, 2016
5917f56
Filestore: Fix typos in README.md
kevina Aug 22, 2016
68ece81
Filestore: Remove note about managled hashed from README.
kevina Aug 26, 2016
ec3ac46
Filestore: Enhance "filestore ls-files" command.
kevina Aug 27, 2016
0b6dc58
Filestore: Add (failing) tests that paths are not modified.
kevina Aug 27, 2016
9090771
Revert "Resolve symlink if it is directly referenced in cli (#2897)"
kevina Aug 27, 2016
6c99d37
Filestore: Path tests now work.
kevina Aug 27, 2016
0c3c9b5
Filestore: Output full paths when added.
kevina Aug 27, 2016
8b396fd
Bug fix for "Add DAGService.GetLinks() method..."
kevina Aug 28, 2016
d8a17f0
Filestore: Add better example script.
kevina Aug 28, 2016
df3f170
Filestore: Add new verification level, Refactor.
kevina Aug 31, 2016
75e61f3
"filestore verify": adjust porcelain output.
kevina Sep 1, 2016
12631ee
Filestore: Fix new example script so it is more correct.
kevina Sep 1, 2016
f4d6a9f
Filestore: Minor Refactor
kevina Sep 1, 2016
b34fd9c
Distinguish between Offline and Local Mode.
kevina Sep 2, 2016
5fd8d6a
Filestore: Store empty files in the filestore itself.
kevina Sep 3, 2016
cdb4951
Filestore: Minor enhancement to example script.
kevina Sep 3, 2016
83f9ec8
Require filestore to be enabled with "filestore enable".
kevina Sep 4, 2016
5e2cac2
Blockstore: Minor refactor of RmBlocks.
kevina Sep 6, 2016
ebf86f2
Adder: Don't hold the PinLock when not pinning.
kevina Sep 7, 2016
ba8060d
Filestore: Bug fix when adding files in "online" mode.
kevina Sep 9, 2016
8f342a7
Filestore: Fix a race condition when updating DataObj
kevina Sep 6, 2016
84e73c3
Filestore: Better logic in Update() method
kevina Sep 8, 2016
5cd6a93
Filestore: Fix maintenance commands so they are safe to run Online
kevina Sep 10, 2016
38ad631
Filestore: Remove OrigData from ListRes and use iterators instead
kevina Sep 9, 2016
e318684
Filestore: Use iterator in VerifyFull. Other refactoring.
kevina Sep 9, 2016
602abc0
Filestore: Rework list filtering so it also works on verify command.
kevina Sep 9, 2016
c75bca3
Filestore: Enhance add-dir.py script to work without cache file.
kevina Sep 10, 2016
3ac9b1a
Filestore: Clarify verify levels, minor refactor
kevina Sep 10, 2016
5238994
Filestore: Remove unused function.
kevina Sep 11, 2016
4c8950e
Filestore: Redo "clean" command so it works again and related changes.
kevina Sep 13, 2016
c515ca0
"filestore clean": Avoid blocking while holidng the GCLock
kevina Sep 13, 2016
c27121b
Filestore: Bug fix to example script.
kevina Sep 15, 2016
4f6a43a
"block rm": Just return "error" in ProcRmOutput.
kevina Sep 15, 2016
5ab877b
"block rm": Document RemovedBlock, rename CheckPins to FilterPinned.
kevina Sep 15, 2016
9871144
Filestore: Rename example script. Update README. Document Filestore.V…
kevina Sep 16, 2016
15e6ec7
Adder: Make sure errors from addAllAndPin make it to the client
kevina Sep 16, 2016
6857aec
Filestore: Fail cleanly when adding symlinks with daemon running.
kevina Sep 16, 2016
4cf2e8c
Merge commit '19779b3707827355f3b9d6c5fbd17e924ea42e91' into kevina/f…
kevina Sep 22, 2016
43bdd07
Merge commit '8ffab98d55628cf590f363ab203da2d4ba160ba2' into kevina/f…
kevina Sep 22, 2016
580fb9f
Merge commit '8830aae9bcef257b11401b7c9e834a3aa107386a' into kevina/f…
kevina Sep 22, 2016
157055b
Merge commit '531b89abc980d2a0080baa0baa0b41638e559b3a' into kevina/f…
kevina Sep 22, 2016
7728d47
Redo 582e5dee3a97f994e7d204ed23960f5752f86553
kevina Sep 22, 2016
97f1ca2
Merge branch 'blockservice-fix' into kevina/filestore
kevina Sep 22, 2016
43d7d8e
Merge commit '87ecb92fceb58497268f7460ac1c877a97b056df' into blockser…
kevina Sep 23, 2016
9709cb5
Merge branch 'blockservice-fix' into kevina/filestore
kevina Sep 23, 2016
3f6214b
Merge remote-tracking branch 'upstream/master' into kevina/filestore
kevina Sep 23, 2016
f478548
Run gofmt on some files, other diff noise cleanup.
kevina Sep 25, 2016
73130fe
Don't use a separate LinkService for DAGService.GetLinks()
kevina Oct 1, 2016
3af102a
Fix EnumerateChildren & hasChild to take a *cid.Cid instead of []*mda…
kevina Oct 4, 2016
739e27c
Revert "Adder: Make sure errors from addAllAndPin make it to the client"
kevina Sep 29, 2016
24cff3a
Revert "Redo 582e5dee3a97f994e7d204ed23960f5752f86553"
kevina Oct 14, 2016
a855ab3
Merge remote-tracking branch 'upstream/master' into kevina/filestore
kevina Oct 15, 2016
e74f619
Filestore: Use the new write-though block service.
kevina Oct 15, 2016
241d10d
Filestore: Disable config.Filestore.APIServerSidePaths for now.
kevina Oct 4, 2016
51f71e1
Clean up diff noise.
kevina Oct 16, 2016
0e045c6
Clarify reason for Has() in Put() in MultiBlockstore.
kevina Oct 4, 2016
5c3b48b
In NewBlockstoreWPrefix don't assume "" is the default value.
kevina Oct 4, 2016
3d0f2e0
Add test that PosInfo() is getting set.
kevina Oct 17, 2016
ba807ea
blockstore: use helper func to convert from Cid to DsKey and the reverse
kevina Oct 16, 2016
d3f0a59
Adder: Disallow adding multiple directories unless "-w" is used.
kevina Oct 5, 2016
85908c2
Adder: fixups
kevina Oct 17, 2016
15fa70a
Filestore: Accommodate systems without sub-second mod-times in tests
kevina Oct 17, 2016
a32f091
Filestore: bug fix, go 'case' does not fall-through
kevina Oct 17, 2016
b9ad427
Filestore: Change the default value of Filestore.Verify to 'Always'
kevina Oct 17, 2016
db6c9e8
Filestore: Verify level 6 behavior now depends on Filestore.Verify
kevina Oct 17, 2016
97933ac
Filestore: Fix sharness test.
kevina Oct 17, 2016
2c58788
Filestore: Fix comment.
kevina Oct 17, 2016
d283e7e
Merge remote-tracking branch 'upstream/kevina/posinfo-2' into kevina/…
kevina Nov 4, 2016
85f1089
Gofmt and other diff noise cleanup.
kevina Oct 18, 2016
9e6636d
Filestore: Support Raw Blocks.
kevina Oct 19, 2016
f080bdb
Merge remote-tracking branch 'upstream/master' into kevina/filestore
kevina Nov 4, 2016
0313956
Filestore: Enable default LevelDB Compression By Default
kevina Oct 20, 2016
77bf0c3
Filestore: Move custom version of filepath.Clean() into its own package.
kevina Oct 20, 2016
f3d5399
Filestore: Use the CidToDsKey form ds-help package.
kevina Nov 4, 2016
3a2b2a0
Filestore: Implement Key struct for future multi DataObj per hash sup…
kevina Oct 21, 2016
b028088
Filestore: Move snapshot related code into its own file.
kevina Oct 21, 2016
c69cd67
Filestore: Remove support for old format and Upgrade command.
kevina Oct 22, 2016
cdd0b69
Filestore: Prep work for multi DataObj per hash support.
kevina Oct 23, 2016
b0e2d0d
Filestore: Enhance Key structure.
kevina Oct 24, 2016
4bd48f8
Filestore: Basic support for multiple DataObjs per hash
kevina Oct 25, 2016
4da34e4
Filestore: Fix maintenance commands.
kevina Oct 28, 2016
6d292b8
Filestore: Remove seperate veirfy-post-orphan command.
kevina Oct 28, 2016
dfc5342
Filestore: enhance "ls" and "verify" command
kevina Oct 30, 2016
4bd3d40
Filestore: Enhance "rm" command.
kevina Oct 31, 2016
12d62f4
Filestore: Documentation updates and improvements.
kevina Oct 31, 2016
c64c0e6
Filestore "ls": Enhance "w/type" format.
kevina Nov 5, 2016
ae0f4a9
Filestore: Improve shareness test descriptions.
kevina Nov 7, 2016
9215a1e
Revert "Filestore: Disable config.Filestore.APIServerSidePaths for now."
kevina Nov 7, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion blocks/blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ import (

var ErrWrongHash = errors.New("data did not match given hash!")

// Block is a singular block of data in ipfs

type Block interface {
RawData() []byte
Cid() *cid.Cid
String() string
Loggable() map[string]interface{}
}

// Block is a singular block of data in ipfs
type BasicBlock struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aww, renaming this from RawBlock to BasicBlock makes the diff so noisy... I was hoping to avoid that by getting that change merged separately

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I missed that change as it was in a separate commit. Let me know if you know if you want me to do anything about it, like submitting this change separately.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@whyrusleeping, this rename is only in one file, it is exported because I might eventually refactor my Filestore specific changes to blocks/blocks.go into another file.

cid *cid.Cid
data []byte
Expand Down
31 changes: 14 additions & 17 deletions blocks/blockstore/blockstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import (
var log = logging.Logger("blockstore")

// BlockPrefix namespaces blockstore datastores
var BlockPrefix = ds.NewKey("blocks")
const DefaultPrefix = "/blocks"

var blockPrefix = ds.NewKey(DefaultPrefix)

var ValueTypeMismatch = errors.New("the retrieved value is not a Block")
var ErrHashMismatch = errors.New("block in storage has different hash than requested")
Expand Down Expand Up @@ -71,20 +73,23 @@ type gcBlockstore struct {
}

func NewBlockstore(d ds.Batching) *blockstore {
return NewBlockstoreWPrefix(d, DefaultPrefix)
}

func NewBlockstoreWPrefix(d ds.Batching, prefix string) *blockstore {
var dsb ds.Batching
dd := dsns.Wrap(d, BlockPrefix)
prefixKey := ds.NewKey(prefix)
dd := dsns.Wrap(d, prefixKey)
dsb = dd
return &blockstore{
datastore: dsb,
prefix: prefixKey,
}
}

type blockstore struct {
datastore ds.Batching

lk sync.RWMutex
gcreq int32
gcreqlk sync.Mutex
prefix ds.Key

rehash bool
}
Expand Down Expand Up @@ -130,11 +135,8 @@ func (bs *blockstore) Get(k *cid.Cid) (blocks.Block, error) {
func (bs *blockstore) Put(block blocks.Block) error {
k := dshelp.CidToDsKey(block.Cid())

// Has is cheaper than Put, so see if we already have it
exists, err := bs.datastore.Has(k)
if err == nil && exists {
return nil // already stored.
}
// Note: The Has Check is now done by the MultiBlockstore

return bs.datastore.Put(k, block.RawData())
}

Expand All @@ -145,11 +147,6 @@ func (bs *blockstore) PutMany(blocks []blocks.Block) error {
}
for _, b := range blocks {
k := dshelp.CidToDsKey(b.Cid())
exists, err := bs.datastore.Has(k)
if err == nil && exists {
continue
}

err = t.Put(k, b.RawData())
if err != nil {
return err
Expand All @@ -175,7 +172,7 @@ func (bs *blockstore) AllKeysChan(ctx context.Context) (<-chan *cid.Cid, error)
// KeysOnly, because that would be _a lot_ of data.
q := dsq.Query{KeysOnly: true}
// datastore/namespace does *NOT* fix up Query.Prefix
q.Prefix = BlockPrefix.String()
q.Prefix = bs.prefix.String()
res, err := bs.datastore.Query(q)
if err != nil {
return nil, err
Expand Down
4 changes: 2 additions & 2 deletions blocks/blockstore/blockstore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func TestAllKeysRespectsContext(t *testing.T) {
default:
}

e := dsq.Entry{Key: BlockPrefix.ChildString("foo").String()}
e := dsq.Entry{Key: blockPrefix.ChildString("foo").String()}
resultChan <- dsq.Result{Entry: e} // let it go.
close(resultChan)
<-done // should be done now.
Expand All @@ -190,7 +190,7 @@ func TestValueTypeMismatch(t *testing.T) {
block := blocks.NewBlock([]byte("some data"))

datastore := ds.NewMapDatastore()
k := BlockPrefix.Child(dshelp.CidToDsKey(block.Cid()))
k := blockPrefix.Child(dshelp.CidToDsKey(block.Cid()))
datastore.Put(k, "data that isn't a block!")

blockstore := NewBlockstore(ds_sync.MutexWrap(datastore))
Expand Down
6 changes: 3 additions & 3 deletions blocks/blockstore/bloom_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ func TestHasIsBloomCached(t *testing.T) {
block := blocks.NewBlock([]byte("newBlock"))

cachedbs.PutMany([]blocks.Block{block})
if cacheFails != 2 {
t.Fatalf("expected two datastore hits: %d", cacheFails)
if cacheFails != 1 {
t.Fatalf("expected datastore hits: %d", cacheFails)
}
cachedbs.Put(block)
if cacheFails != 3 {
if cacheFails != 2 {
t.Fatalf("expected datastore hit: %d", cacheFails)
}

Expand Down
158 changes: 158 additions & 0 deletions blocks/blockstore/multi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package blockstore

// A very simple multi-blockstore that analogous to a unionfs Put and
// DeleteBlock only go to the first blockstore all others are
// considered readonly.

import (
//"errors"
"context"

blocks "github.com/ipfs/go-ipfs/blocks"
cid "gx/ipfs/QmXfiyr2RWEXpVDdaYnD2HNiBk6UBddsvEP4RPfXb6nGqY/go-cid"
dsq "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore/query"
)

type LocateInfo struct {
Prefix string
Error error
}

type MultiBlockstore interface {
Blockstore
GCLocker
FirstMount() Blockstore
Mounts() []string
Mount(prefix string) Blockstore
Locate(*cid.Cid) []LocateInfo
}

type Mount struct {
Prefix string
Blocks Blockstore
}

func NewMultiBlockstore(mounts ...Mount) *multiblockstore {
return &multiblockstore{
mounts: mounts,
}
}

type multiblockstore struct {
mounts []Mount
gclocker
}

func (bs *multiblockstore) FirstMount() Blockstore {
return bs.mounts[0].Blocks
}

func (bs *multiblockstore) Mounts() []string {
mounts := make([]string, 0, len(bs.mounts))
for _, mnt := range bs.mounts {
mounts = append(mounts, mnt.Prefix)
}
return mounts
}

func (bs *multiblockstore) Mount(prefix string) Blockstore {
for _, m := range bs.mounts {
if m.Prefix == prefix {
return m.Blocks
}
}
return nil
}

func (bs *multiblockstore) DeleteBlock(key *cid.Cid) error {
return bs.mounts[0].Blocks.DeleteBlock(key)
}

func (bs *multiblockstore) Has(c *cid.Cid) (bool, error) {
var firstErr error
for _, m := range bs.mounts {
have, err := m.Blocks.Has(c)
if have && err == nil {
return have, nil
}
if err != nil && firstErr == nil {
firstErr = err
}
}
return false, firstErr
}

func (bs *multiblockstore) Get(c *cid.Cid) (blocks.Block, error) {
var firstErr error
for _, m := range bs.mounts {
blk, err := m.Blocks.Get(c)
if err == nil {
return blk, nil
}
if firstErr == nil || firstErr == ErrNotFound {
firstErr = err
}
}
return nil, firstErr
}

func (bs *multiblockstore) Locate(c *cid.Cid) []LocateInfo {
res := make([]LocateInfo, 0, len(bs.mounts))
for _, m := range bs.mounts {
_, err := m.Blocks.Get(c)
res = append(res, LocateInfo{m.Prefix, err})
}
return res
}

func (bs *multiblockstore) Put(blk blocks.Block) error {
// First call Has() to make sure the block doesn't exist in any of
// the sub-blockstores, otherwise we could end with data being
// duplicated in two blockstores.
exists, err := bs.Has(blk.Cid())
if err == nil && exists {
return nil // already stored
}
return bs.mounts[0].Blocks.Put(blk)
}

func (bs *multiblockstore) PutMany(blks []blocks.Block) error {
stilladd := make([]blocks.Block, 0, len(blks))
// First call Has() to make sure the block doesn't exist in any of
// the sub-blockstores, otherwise we could end with data being
// duplicated in two blockstores.
for _, blk := range blks {
exists, err := bs.Has(blk.Cid())
if err == nil && exists {
continue // already stored
}
stilladd = append(stilladd, blk)
}
if len(stilladd) == 0 {
return nil
}
return bs.mounts[0].Blocks.PutMany(stilladd)
}

func (bs *multiblockstore) AllKeysChan(ctx context.Context) (<-chan *cid.Cid, error) {
//return bs.mounts[0].Blocks.AllKeysChan(ctx)
//return nil, errors.New("Unimplemented")
in := make([]<-chan *cid.Cid, 0, len(bs.mounts))
for _, m := range bs.mounts {
ch, err := m.Blocks.AllKeysChan(ctx)
if err != nil {
return nil, err
}
in = append(in, ch)
}
out := make(chan *cid.Cid, dsq.KeysOnlyBufSize)
go func() {
defer close(out)
for _, in0 := range in {
for key := range in0 {
out <- key
}
}
}()
return out, nil
}
29 changes: 24 additions & 5 deletions blocks/blockstore/util/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,23 @@ type RmBlocksOpts struct {
Force bool
}

func RmBlocks(blocks bs.GCBlockstore, pins pin.Pinner, out chan<- interface{}, cids []*cid.Cid, opts RmBlocksOpts) error {
func RmBlocks(mbs bs.MultiBlockstore, pins pin.Pinner, out chan<- interface{}, cids []*cid.Cid, opts RmBlocksOpts) error {
prefix := opts.Prefix
if prefix == "" {
prefix = mbs.Mounts()[0]
}
blocks := mbs.Mount(prefix)
if blocks == nil {
return fmt.Errorf("Could not find blockstore: %s\n", prefix)
}

go func() {
defer close(out)

unlocker := blocks.GCLock()
unlocker := mbs.GCLock()
defer unlocker.Unlock()

stillOkay := FilterPinned(pins, out, cids)
stillOkay := FilterPinned(mbs, pins, out, cids, prefix)

for _, c := range stillOkay {
err := blocks.DeleteBlock(c)
Expand All @@ -50,15 +59,15 @@ func RmBlocks(blocks bs.GCBlockstore, pins pin.Pinner, out chan<- interface{}, c
return nil
}

func FilterPinned(pins pin.Pinner, out chan<- interface{}, cids []*cid.Cid) []*cid.Cid {
func FilterPinned(mbs bs.MultiBlockstore, pins pin.Pinner, out chan<- interface{}, cids []*cid.Cid, prefix string) []*cid.Cid {
stillOkay := make([]*cid.Cid, 0, len(cids))
res, err := pins.CheckIfPinned(cids...)
if err != nil {
out <- &RemovedBlock{Error: fmt.Sprintf("pin check failed: %s", err)}
return nil
}
for _, r := range res {
if !r.Pinned() {
if !r.Pinned() || AvailableElsewhere(mbs, prefix, r.Key) {
stillOkay = append(stillOkay, r.Key)
} else {
out <- &RemovedBlock{
Expand All @@ -70,6 +79,16 @@ func FilterPinned(pins pin.Pinner, out chan<- interface{}, cids []*cid.Cid) []*c
return stillOkay
}

func AvailableElsewhere(mbs bs.MultiBlockstore, prefix string, c *cid.Cid) bool {
locations := mbs.Locate(c)
for _, loc := range locations {
if loc.Error == nil && loc.Prefix != prefix {
return true
}
}
return false
}

func ProcRmOutput(in <-chan interface{}, sout io.Writer, serr io.Writer) error {
someFailed := false
for res := range in {
Expand Down
2 changes: 2 additions & 0 deletions cmd/ipfs/ipfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,6 @@ var cmdDetailsMap = map[*cmds.Command]cmdDetails{
commands.ActiveReqsCmd: {cannotRunOnClient: true},
commands.RepoFsckCmd: {cannotRunOnDaemon: true},
commands.ConfigCmd.Subcommand("edit"): {cannotRunOnDaemon: true, doesNotUseRepo: true},
commands.FilestoreEnable: {cannotRunOnDaemon: true},
commands.FilestoreDisable: {cannotRunOnDaemon: true},
}
4 changes: 4 additions & 0 deletions commands/files/slicefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ func (f *SliceFile) IsDirectory() bool {
return true
}

func (f *SliceFile) NumFiles() int {
return len(f.files)
}

func (f *SliceFile) NextFile() (File, error) {
if f.n >= len(f.files) {
return nil, io.EOF
Expand Down
Loading