Skip to content

Commit

Permalink
feat(CAFS): repurpose CAFS acronym as a filesystem property
Browse files Browse the repository at this point in the history
add an interface that allows Filesytems to distinguish when they use refer-by-hash
by opting into the CAFS interface. In the future we may want to expand this interface
with values for working with hashes, but for now just distinguishing which Filesystems
are content-addressed is enough.
  • Loading branch information
b5 committed Nov 17, 2020
1 parent f5c12e4 commit 0e309e0
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 11 deletions.
8 changes: 8 additions & 0 deletions fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ type PinningFS interface {
Unpin(ctx context.Context, key string, recursive bool) error
}

// CAFS stands for "content-addressed filesystem". Filesystem that implement
// this interface declare that all paths to persisted content are reference-by
// -hash.
// TODO (b5) - write up a spec test suite for CAFS conformance
type CAFS interface {
IsContentAddressedFilesystem()
}

// AbsPath adjusts the provided string to a path lib functions can work with
// because paths for Qri can come from the local filesystem, an http url, or
// the distributed web, Absolutizing is a little tricky
Expand Down
28 changes: 17 additions & 11 deletions mem.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,25 @@ type MemFS struct {
Files map[string]filer
}

// compile-time assertion that MemFS satisfies the Filesystem interface
var _ Filesystem = (*MemFS)(nil)
var (
// compile-time assertion that MemFS satisfies the Filesystem interface
_ Filesystem = (*MemFS)(nil)
// assert MemFS implements the CAFS interface
_ CAFS = (*MemFS)(nil)
)

// MemFilestoreType uniquely identifies the mem filestore
const MemFilestoreType = "mem"

// Type distinguishes this filesystem from others by a unique string prefix
func (m MemFS) Type() string {
func (m *MemFS) Type() string {
return MemFilestoreType
}

func (m *MemFS) IsContentAddressedFilesystem() {}

// Print converts the store to a string
func (m MemFS) Print() (string, error) {
func (m *MemFS) Print() (string, error) {
m.filesLk.Lock()
defer m.filesLk.Unlock()

Expand All @@ -90,7 +96,7 @@ func (m MemFS) Print() (string, error) {
}

// ObjectCount returns the number of content-addressed objects in the store
func (m MemFS) ObjectCount() (objects int) {
func (m *MemFS) ObjectCount() (objects int) {
for range m.Files {
objects++
}
Expand Down Expand Up @@ -241,15 +247,15 @@ func (m *MemFS) getLocal(key string) (File, error) {
}

// Has returns whether the store has a File with the key
func (m MemFS) Has(ctx context.Context, key string) (exists bool, err error) {
func (m *MemFS) Has(ctx context.Context, key string) (exists bool, err error) {
if _, err := m.getLocal(key); err == nil {
return true, nil
}
return false, nil
}

// Delete removes the file from the store with the key
func (m MemFS) Delete(ctx context.Context, key string) error {
func (m *MemFS) Delete(ctx context.Context, key string) error {

key = strings.TrimPrefix(key, fmt.Sprintf("/%s/", MemFilestoreType))
// key may be of the form /mem/QmFoo/file.json but MemFS indexes its maps
Expand Down Expand Up @@ -321,15 +327,15 @@ func (m *MemFS) AddConnection(other *MemFS) {
}

type adder struct {
fs MemFS
fs *MemFS
pin bool
out chan AddedFile
root string
tree *nd
}

// NewAdder returns an Adder for the store
func (m MemFS) NewAdder(ctx context.Context, pin, wrap bool) (Adder, error) {
func (m *MemFS) NewAdder(ctx context.Context, pin, wrap bool) (Adder, error) {
addedOut := make(chan AddedFile, 9)
return &adder{
fs: m,
Expand Down Expand Up @@ -373,7 +379,7 @@ func (a *adder) AddFile(ctx context.Context, f File) (err error) {

if f.IsDirectory() {
var dir fsDir
hash, dir = node.toDir(&a.fs)
hash, dir = node.toDir(a.fs)
if err != nil {
return err
}
Expand Down Expand Up @@ -413,7 +419,7 @@ func (a *adder) Finalize() (string, error) {
log.Debugf("adding root directory")
root := NewMemdir("/")
node := a.addNode(root)
hash, dir := node.toDir(&a.fs)
hash, dir := node.toDir(a.fs)
a.fs.filesLk.Lock()
a.fs.Files[hash] = dir
a.fs.filesLk.Unlock()
Expand Down
4 changes: 4 additions & 0 deletions qipfs/filestore.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type Filestore struct {
var (
_ qfs.ReleasingFilesystem = (*Filestore)(nil)
_ cafs.Fetcher = (*Filestore)(nil)
_ qfs.CAFS = (*Filestore)(nil)
)

// NewFilesystem creates a new local filesystem PathResolver
Expand Down Expand Up @@ -150,6 +151,9 @@ func (fst Filestore) Type() string {
return FilestoreType
}

// IsContentAddressedFilesystem declares qipfs is content-addressed
func (fst Filestore) IsContentAddressedFilesystem() {}

// Done implements the qfs.ReleasingFilesystem interface
func (fst *Filestore) Done() <-chan struct{} {
return fst.doneCh
Expand Down

0 comments on commit 0e309e0

Please sign in to comment.