func TestAllocateMultiple(t *testing.T) { tmp, err := ioutil.TempFile("", "bazil-test-inodes-") if err != nil { t.Fatal(err) } defer func() { tmp.Close() os.Remove(tmp.Name()) }() db, err := bolt.Open(tmp.Name(), 0666) if err != nil { t.Fatal(err) } defer db.Close() var inodeBucketName = []byte("inodetest") db.Update(func(tx *bolt.Tx) error { _, err := tx.CreateBucketIfNotExists(inodeBucketName) return err }) const firstInode = 1024 for i := uint64(firstInode); i < firstInode+100; i += 2 { var gotOne, gotTwo uint64 f := func(tx *bolt.Tx) error { bucket := tx.Bucket(inodeBucketName) if bucket == nil { return fmt.Errorf("inode bucket missing in test: %q", inodeBucketName) } var err error gotOne, err = inodes.Allocate(bucket) if err != nil { return err } gotTwo, err = inodes.Allocate(bucket) return err } if err := db.Update(f); err != nil { t.Error(err) } if g, e := gotOne, i; g != e { t.Errorf("wrong inode allocated: %d != %d", g, e) } if g, e := gotTwo, i+1; g != e { t.Errorf("wrong inode allocated: %d != %d", g, e) } } }
func (d *dir) Mkdir(req *fuse.MkdirRequest, intr fs.Intr) (fs.Node, fuse.Error) { d.mu.Lock() defer d.mu.Unlock() // TODO handle req.Mode 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 } child = &dir{ inode: inode, name: req.Name, parent: d, fs: d.fs, active: make(map[string]node), } d.active[req.Name] = child return d.saveInternal(tx, req.Name, child) // TODO clean up active on error }) if err != nil { if err == inodes.OutOfInodes { return nil, fuse.Errno(syscall.ENOSPC) } return nil, err } return child, nil }
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 } }