예제 #1
0
func (s *apiServer) Create(ctx context.Context, r *pb.CreateRequest) (*pb.CreateResponse, error) {
	err := s.validateIP(ctx)
	if err != nil {
		return nil, err
	}
	fsid, err := GetFsId(ctx)
	if err != nil {
		return nil, err
	}
	ts := time.Now().Unix()
	inode := s.fl.GetID()
	attr := &pb.Attr{
		Inode:  inode,
		Atime:  ts,
		Mtime:  ts,
		Ctime:  ts,
		Crtime: ts,
		Mode:   r.Attr.Mode,
		Uid:    r.Attr.Uid,
		Gid:    r.Attr.Gid,
	}
	rname, rattr, err := s.fs.Create(ctx, formic.GetID(fsid.Bytes(), r.Parent, 0), formic.GetID(fsid.Bytes(), inode, 0), inode, r.Name, attr, false)
	if err != nil {
		return nil, err
	}
	return &pb.CreateResponse{Name: rname, Attr: rattr}, err
}
예제 #2
0
func (s *apiServer) Write(ctx context.Context, r *pb.WriteRequest) (*pb.WriteResponse, error) {
	err := s.validateIP(ctx)
	if err != nil {
		return nil, err
	}
	fsid, err := GetFsId(ctx)
	if err != nil {
		return nil, err
	}
	log.Printf("WRITE: Inode %d Offset: %d Size: %d", r.Inode, r.Offset, len(r.Payload))
	block := uint64(r.Offset / s.blocksize)
	firstOffset := int64(0)
	if r.Offset%s.blocksize != 0 {
		// Handle non-aligned offset
		firstOffset = r.Offset - int64(block)*s.blocksize
	}
	cur := int64(0)
	for cur < int64(len(r.Payload)) {
		sendSize := min(s.blocksize, int64(len(r.Payload))-cur)
		if sendSize+firstOffset > s.blocksize {
			sendSize = s.blocksize - firstOffset
		}
		payload := r.Payload[cur : cur+sendSize]
		id := formic.GetID(fsid.Bytes(), r.Inode, block+1) // 0 block is for inode data
		if firstOffset > 0 || sendSize < s.blocksize {
			// need to get the block and update
			chunk := make([]byte, firstOffset+int64(len(payload)))
			data, err := s.fs.GetChunk(ctx, id)
			if firstOffset > 0 && err != nil {
				// TODO: How do we differentiate a block that hasn't been created yet, and a block that is truely missing?
				log.Printf("WARN: couldn't get block id %d", id)
			} else {
				if len(data) > len(chunk) {
					chunk = data
				} else {
					copy(chunk, data)
				}
			}
			copy(chunk[firstOffset:], payload)
			payload = chunk
			firstOffset = 0
		}
		err := s.fs.WriteChunk(ctx, id, payload)
		// TODO: Need better error handling for failing with multiple chunks
		if err != nil {
			return &pb.WriteResponse{Status: 1}, err
		}
		s.updateChan <- &UpdateItem{
			id:        formic.GetID(fsid.Bytes(), r.Inode, 0),
			block:     block,
			blocksize: uint64(s.blocksize),
			size:      uint64(len(payload)),
			mtime:     time.Now().Unix(),
		}
		cur += sendSize
		block += 1
	}
	return &pb.WriteResponse{Status: 0}, nil
}
예제 #3
0
func TestGetID(t *testing.T) {
	id1 := formic.GetID([]byte("1"), uint64(1), uint64(1))
	id2 := formic.GetID([]byte("1"), uint64(1), uint64(1))
	if !bytes.Equal(id1, id2) {
		t.Errorf("Generated IDs not equal")
	}
	id3 := formic.GetID([]byte("1"), uint64(1), uint64(2))
	if bytes.Equal(id1, id3) {
		t.Errorf("Generated IDs were equal")
	}
}
예제 #4
0
func (s *apiServer) Rename(ctx context.Context, r *pb.RenameRequest) (*pb.RenameResponse, error) {
	err := s.validateIP(ctx)
	if err != nil {
		return nil, err
	}
	fsid, err := GetFsId(ctx)
	if err != nil {
		return nil, err
	}
	return s.fs.Rename(ctx, formic.GetID(fsid.Bytes(), r.OldParent, 0), formic.GetID(fsid.Bytes(), r.NewParent, 0), r.OldName, r.NewName)
}
예제 #5
0
func (d *Deletinator) run() {
	// TODO: Parallelize this thing?
	for {
		todelete := <-d.in
		log.Println("Deleting: ", todelete)
		// TODO: Need better context
		ctx := context.Background()
		// Get the dir entry info
		dirent, err := d.fs.GetDirent(ctx, todelete.parent, todelete.name)
		if store.IsNotFound(err) {
			// NOTE: If it isn't found then it is likely deleted.
			//       Do we need to do more to ensure this?
			//       Skip for now
			continue
		}
		if err != nil {
			// TODO Better error handling?
			// re-q the id, to try again later
			log.Print("Delete error getting dirent: ", err)
			d.in <- todelete
			continue
		}
		ts := dirent.Tombstone
		deleted := uint64(0)
		for b := uint64(0); b < ts.Blocks; b++ {
			// Delete each block
			id := formic.GetID(ts.FsId, ts.Inode, b+1)
			err := d.fs.DeleteChunk(ctx, id, ts.Dtime)
			if err != nil && !store.IsNotFound(err) && err != ErrStoreHasNewerValue {
				continue
			}
			deleted++
		}
		if deleted == ts.Blocks {
			// Everything is deleted so delete the entry
			err := d.fs.DeleteChunk(ctx, formic.GetID(ts.FsId, ts.Inode, 0), ts.Dtime)
			if err != nil && !store.IsNotFound(err) && err != ErrStoreHasNewerValue {
				// Couldn't delete the inode entry so try again later
				d.in <- todelete
				continue
			}
			err = d.fs.DeleteListing(ctx, todelete.parent, todelete.name, ts.Dtime)
			if err != nil && !store.IsNotFound(err) && err != ErrStoreHasNewerValue {
				log.Println("  Err: ", err)
				// TODO: Better error handling
				// Ignore for now to be picked up later?
			}
		} else {
			// If all artifacts are not deleted requeue for later
			d.in <- todelete
		}
	}
}
예제 #6
0
func (o *OortFS) InitFs(ctx context.Context, fsid []byte) error {
	id := formic.GetID(fsid, 1, 0)
	n, _ := o.GetChunk(ctx, id)
	if len(n) == 0 {
		log.Println("Creating new root at ", id)
		// Need to create the root node
		r := &pb.InodeEntry{
			Version: InodeEntryVersion,
			Inode:   1,
			IsDir:   true,
			FsId:    fsid,
		}
		ts := time.Now().Unix()
		r.Attr = &pb.Attr{
			Inode:  1,
			Atime:  ts,
			Mtime:  ts,
			Ctime:  ts,
			Crtime: ts,
			Mode:   uint32(os.ModeDir | 0775),
			Uid:    1001, // TODO: need to config default user/group id
			Gid:    1001,
		}
		b, err := proto.Marshal(r)
		if err != nil {
			return err
		}
		err = o.WriteChunk(ctx, id, b)
		if err != nil {
			return err
		}
	}
	return nil
}
예제 #7
0
func (s *apiServer) Removexattr(ctx context.Context, r *pb.RemovexattrRequest) (*pb.RemovexattrResponse, error) {
	err := s.validateIP(ctx)
	if err != nil {
		return nil, err
	}
	fsid, err := GetFsId(ctx)
	if err != nil {
		return nil, err
	}
	return s.fs.Removexattr(ctx, formic.GetID(fsid.Bytes(), r.Inode, 0), r.Name)
}
예제 #8
0
func (s *apiServer) ReadDirAll(ctx context.Context, n *pb.ReadDirAllRequest) (*pb.ReadDirAllResponse, error) {
	err := s.validateIP(ctx)
	if err != nil {
		return nil, err
	}
	fsid, err := GetFsId(ctx)
	if err != nil {
		return nil, err
	}
	return s.fs.ReadDirAll(ctx, formic.GetID(fsid.Bytes(), n.Inode, 0))
}
예제 #9
0
func (s *apiServer) Remove(ctx context.Context, r *pb.RemoveRequest) (*pb.RemoveResponse, error) {
	err := s.validateIP(ctx)
	if err != nil {
		return nil, err
	}
	fsid, err := GetFsId(ctx)
	if err != nil {
		return nil, err
	}
	status, err := s.fs.Remove(ctx, formic.GetID(fsid.Bytes(), r.Parent, 0), r.Name)
	return &pb.RemoveResponse{Status: status}, err
}
예제 #10
0
func (s *apiServer) Lookup(ctx context.Context, r *pb.LookupRequest) (*pb.LookupResponse, error) {
	err := s.validateIP(ctx)
	if err != nil {
		return nil, err
	}
	fsid, err := GetFsId(ctx)
	if err != nil {
		return nil, err
	}
	name, attr, err := s.fs.Lookup(ctx, formic.GetID(fsid.Bytes(), r.Parent, 0), r.Name)
	return &pb.LookupResponse{Name: name, Attr: attr}, err
}
예제 #11
0
func (s *apiServer) SetAttr(ctx context.Context, r *pb.SetAttrRequest) (*pb.SetAttrResponse, error) {
	err := s.validateIP(ctx)
	if err != nil {
		return nil, err
	}
	fsid, err := GetFsId(ctx)
	if err != nil {
		return nil, err
	}
	attr, err := s.fs.SetAttr(ctx, formic.GetID(fsid.Bytes(), r.Attr.Inode, 0), r.Attr, r.Valid)
	return &pb.SetAttrResponse{Attr: attr}, err
}
예제 #12
0
func (s *apiServer) Symlink(ctx context.Context, r *pb.SymlinkRequest) (*pb.SymlinkResponse, error) {
	err := s.validateIP(ctx)
	if err != nil {
		return nil, err
	}
	fsid, err := GetFsId(ctx)
	if err != nil {
		return nil, err
	}
	ts := time.Now().Unix()
	inode := s.fl.GetID()
	attr := &pb.Attr{
		Inode:  inode,
		Atime:  ts,
		Mtime:  ts,
		Ctime:  ts,
		Crtime: ts,
		Mode:   uint32(os.ModeSymlink | 0755),
		Size:   uint64(len(r.Target)),
		Uid:    r.Uid,
		Gid:    r.Gid,
	}
	return s.fs.Symlink(ctx, formic.GetID(fsid.Bytes(), r.Parent, 0), formic.GetID(fsid.Bytes(), inode, 0), r.Name, r.Target, attr, inode)
}
예제 #13
0
func (s *apiServer) Read(ctx context.Context, r *pb.ReadRequest) (*pb.ReadResponse, error) {
	err := s.validateIP(ctx)
	if err != nil {
		return nil, err
	}
	fsid, err := GetFsId(ctx)
	if err != nil {
		return nil, err
	}
	log.Printf("READ: Inode: %d Offset: %d Size: %d", r.Inode, r.Offset, r.Size)
	block := uint64(r.Offset / s.blocksize)
	data := make([]byte, r.Size)
	firstOffset := int64(0)
	if r.Offset%s.blocksize != 0 {
		// Handle non-aligned offset
		firstOffset = r.Offset - int64(block)*s.blocksize
	}
	cur := int64(0)
	for cur < r.Size {
		id := formic.GetID(fsid.Bytes(), r.Inode, block+1) // block 0 is for inode data
		chunk, err := s.fs.GetChunk(ctx, id)
		if err != nil {
			log.Print("Err: Failed to read block: ", err)
			// NOTE: This returns basically 0's to the client.for this block in this case
			//       It is totally valid for a fs to request an invalid block
			// TODO: Do we need to differentiate between real errors and bad requests?
			return &pb.ReadResponse{}, nil
		}
		if len(chunk) == 0 {
			break
		}
		count := copy(data[cur:], chunk[firstOffset:])
		firstOffset = 0
		block += 1
		cur += int64(count)
		if int64(len(chunk)) < s.blocksize {
			break
		}
	}
	f := &pb.ReadResponse{Inode: r.Inode, Payload: data}
	return f, nil
}