func setup_dir(t testing.TB, chunkStore chunks.Store, dirents []*wire.Dirent) *wire.Dirent { blob, err := blobs.Open( chunkStore, blobs.EmptyManifest("dir"), ) if err != nil { t.Fatalf("unexpected blob open error: %v", err) } w := snap.NewWriter(blob) for _, de := range dirents { err := w.Add(de) if err != nil { t.Fatalf("unexpected add error: %v", err) } } manifest, err := blob.Save() if err != nil { t.Fatalf("unexpected save error: %v", err) } var de wire.Dirent de.Type.Dir = &wire.Dir{ Manifest: wirecas.FromBlob(manifest), } return &de }
func emptyBlob(t testing.TB, chunkStore chunks.Store) *blobs.Blob { blob, err := blobs.Open( chunkStore, blobs.EmptyManifest("footype"), ) if err != nil { t.Fatalf("cannot open blob: %v", err) } return blob }
func setup_greeting(t testing.TB, chunkStore chunks.Store) *blobs.Manifest { blob, err := blobs.Open( chunkStore, blobs.EmptyManifest("file"), ) if err != nil { t.Fatalf("unexpected blob open error: %v", err) } _, err = blob.WriteAt([]byte(GREETING), 0) if err != nil { t.Fatalf("unexpected write error: %v", err) } manifest, err := blob.Save() if err != nil { t.Fatalf("unexpected save error: %v", err) } return manifest }
func (d *dir) Create(req *fuse.CreateRequest, resp *fuse.CreateResponse, intr fs.Intr) (fs.Node, fs.Handle, fuse.Error) { d.mu.Lock() defer d.mu.Unlock() // TODO check for duplicate name switch req.Mode & os.ModeType { case 0: var child node err := d.fs.db.Update(func(tx *bolt.Tx) error { bucket := d.fs.bucket(tx).Bucket(bucketInode) if bucket == nil { return errors.New("inode bucket is missing") } inode, err := inodes.Allocate(bucket) if err != nil { return err } manifest := blobs.EmptyManifest("file") blob, err := blobs.Open(d.fs.chunkStore, manifest) if err != nil { return fmt.Errorf("blob open problem: %v", err) } child = &file{ inode: inode, name: req.Name, parent: d, blob: blob, } d.active[req.Name] = child return d.saveInternal(tx, req.Name, child) // TODO clean up active on error }) if err != nil { return nil, nil, err } return child, child, nil default: return nil, nil, fuse.EPERM } }
// snapshot records a snapshot of the directory and stores it in wde func (d *dir) snapshot(tx *bolt.Tx, out *wiresnap.Dir, intr fs.Intr) error { // NOT HOLDING THE LOCK, accessing database snapshot ONLY // TODO move bucket lookup to caller? bucket := d.fs.bucket(tx).Bucket(bucketDir) if bucket == nil { return errors.New("dir bucket missing") } manifest := blobs.EmptyManifest("dir") blob, err := blobs.Open(d.fs.chunkStore, manifest) if err != nil { return err } w := snap.NewWriter(blob) c := bucket.Cursor() prefix := pathToKey(d.inode, "") for k, v := c.Seek(prefix); k != nil; k, v = c.Next() { if !bytes.HasPrefix(k, prefix) { // past the end of the directory break } name := string(k[len(prefix):]) de, err := d.unmarshalDirent(v) if err != nil { return err } sde := wiresnap.Dirent{ Name: name, } switch { case de.Type.File != nil: // TODO d.reviveNode would do blobs.Open and that's a bit // too much work; rework the apis sde.Type.File = &wiresnap.File{ Manifest: de.Type.File.Manifest, } case de.Type.Dir != nil: child, err := d.reviveDir(de, name) if err != nil { return err } sde.Type.Dir = &wiresnap.Dir{} err = child.snapshot(tx, sde.Type.Dir, intr) if err != nil { return err } default: return errors.New("TODO") } err = w.Add(&sde) if err != nil { return err } } manifest, err = blob.Save() if err != nil { return err } out.Manifest = wirecas.FromBlob(manifest) out.Align = w.Align() return nil }