func newFS(chunkStore chunks.Store, dir *wire.Dir) (*FS, error) { root, err := snap.Open(chunkStore, dir) if err != nil { return nil, err } return &FS{root: root}, nil }
// Mkdir takes a snapshot of this volume and records it under the // given name. func (d *listSnaps) Mkdir(req *fuse.MkdirRequest, intr fs.Intr) (fs.Node, fuse.Error) { // TODO this lock is too much d.fs.mu.Lock() defer d.fs.mu.Unlock() var snapshot = wiresnap.Snapshot{ Name: req.Name, } err := d.fs.db.View(func(tx *bolt.Tx) error { return d.rootDir.snapshot(tx, &snapshot.Contents, intr) }) if err != nil { return nil, fmt.Errorf("cannot record snapshot: %v", err) } var key cas.Key { buf, err := proto.Marshal(&snapshot) if err != nil { return nil, fmt.Errorf("cannot marshal snapshot: %v", err) } if len(buf) == 0 { return nil, errors.New("marshaled snapshot become empty; this is a bug!") } // store the snapshot as a chunk, for disaster recovery key, err = d.fs.chunkStore.Add(&chunks.Chunk{ Type: "snap", Level: 0, Buf: buf, }) if err != nil { return nil, fmt.Errorf("cannot store snapshot: %v", err) } } var ref = wire.SnapshotRef{ Key: key, } buf, err := proto.Marshal(&ref) if err != nil { return nil, fmt.Errorf("cannot marshal snapshot pointer: %v", err) } err = d.fs.db.Update(func(tx *bolt.Tx) error { b := d.fs.bucket(tx).Bucket(bucketSnap) if b == nil { return errors.New("snapshot bucket missing") } return b.Put([]byte(req.Name), buf) }) n, err := snap.Open(d.fs.chunkStore, &snapshot.Contents) if err != nil { return nil, fmt.Errorf("cannot serve snapshot: %v", err) } return n, nil }
func (d *listSnaps) Lookup(ctx context.Context, name string) (fs.Node, error) { var ref wire.SnapshotRef lookup := func(tx *db.Tx) error { bucket := d.fs.bucket(tx).SnapBucket() if bucket == nil { return errors.New("snapshot bucket missing") } buf := bucket.Get([]byte(name)) if buf == nil { return fuse.ENOENT } if err := proto.Unmarshal(buf, &ref); err != nil { return fmt.Errorf("corrupt snapshot reference: %q: %v", name, err) } return nil } if err := d.fs.db.View(lookup); err != nil { return nil, err } var k cas.Key if err := k.UnmarshalBinary(ref.Key); err != nil { return nil, fmt.Errorf("corrupt snapshot reference: %q: %v", name, err) } chunk, err := d.fs.chunkStore.Get(k, "snap", 0) if err != nil { return nil, fmt.Errorf("cannot fetch snapshot: %v", err) } var snapshot wiresnap.Snapshot err = proto.Unmarshal(chunk.Buf, &snapshot) if err != nil { return nil, fmt.Errorf("corrupt snapshot: %v: %v", ref.Key, err) } n, err := snap.Open(d.fs.chunkStore, snapshot.Contents) if err != nil { return nil, fmt.Errorf("cannot serve snapshot: %v", err) } return n, nil }
func (d *listSnaps) Lookup(name string, intr fs.Intr) (fs.Node, fuse.Error) { var buf []byte err := d.fs.db.View(func(tx *bolt.Tx) error { bucket := d.fs.bucket(tx).Bucket(bucketSnap) if bucket == nil { return errors.New("snapshot bucket missing") } buf := bucket.Get([]byte(name)) if buf == nil { return fuse.ENOENT } return nil }) if err != nil { return nil, err } var ref wire.SnapshotRef err = proto.Unmarshal(buf, &ref) if err != nil { return nil, fmt.Errorf("corrupt snapshot reference: %q: %v", name, err) } chunk, err := d.fs.chunkStore.Get(ref.Key, "snap", 0) if err != nil { return nil, fmt.Errorf("cannot fetch snapshot: %v", err) } var snapshot wiresnap.Snapshot err = proto.Unmarshal(chunk.Buf, &snapshot) if err != nil { return nil, fmt.Errorf("corrupt snapshot: %v: %v", ref.Key, err) } n, err := snap.Open(d.fs.chunkStore, &snapshot.Contents) if err != nil { return nil, fmt.Errorf("cannot serve snapshot: %v", err) } return n, nil }
// Mkdir takes a snapshot of this volume and records it under the // given name. func (d *listSnaps) Mkdir(ctx context.Context, req *fuse.MkdirRequest) (fs.Node, error) { var snapshot *wiresnap.Snapshot record := func(tx *db.Tx) error { s, err := d.fs.Snapshot(ctx, tx) if err != nil { return err } snapshot = s return nil } if err := d.fs.db.View(record); err != nil { return nil, fmt.Errorf("cannot record snapshot: %v", err) } snapshot.Name = req.Name var key cas.Key { buf, err := proto.Marshal(snapshot) if err != nil { return nil, fmt.Errorf("cannot marshal snapshot: %v", err) } if len(buf) == 0 { return nil, errors.New("marshaled snapshot become empty; this is a bug") } // store the snapshot as a chunk, for disaster recovery key, err = d.fs.chunkStore.Add(&chunks.Chunk{ Type: "snap", Level: 0, Buf: buf, }) if err != nil { return nil, fmt.Errorf("cannot store snapshot: %v", err) } } var ref = wire.SnapshotRef{ Key: key.Bytes(), } buf, err := proto.Marshal(&ref) if err != nil { return nil, fmt.Errorf("cannot marshal snapshot pointer: %v", err) } add := func(tx *db.Tx) error { b := d.fs.bucket(tx).SnapBucket() if b == nil { return errors.New("snapshot bucket missing") } return b.Put([]byte(req.Name), buf) } if err := d.fs.db.Update(add); err != nil { return nil, fmt.Errorf("cannot save snapshot pointer: %v", err) } n, err := snap.Open(d.fs.chunkStore, snapshot.Contents) if err != nil { return nil, fmt.Errorf("cannot serve snapshot: %v", err) } return n, nil }