Skip to content
Browse files

fixed up Open()

  • Loading branch information...
1 parent 24c146f commit a6a255870daf7879afd5e0cf0ac980164738d919 @jbooth committed Jul 23, 2012
Showing with 91 additions and 166 deletions.
  1. +30 −69 file.go
  2. +38 −28 fuseconnector.go
  3. +3 −42 memnames.go
  4. +16 −12 services.go
  5. +4 −15 types.go
View
99 file.go
@@ -1,7 +1,8 @@
package maggiefs
import (
- "io"
+ "fmt"
+ "errors"
)
@@ -16,95 +17,55 @@ func NewWriter(inode Inode, datas DataService) (w *Writer, err error) {
// maintains a one page buffer for reading
// for writable or RW files, see OpenWriteFile
type Reader struct {
- path PathEntry
inode Inode
- buffer []byte
- globalPos uint64 // pos in file
- blockPos uint32 // pos within block
- bufferPos uint32 // pos within buffer
- pageNum uint64 // current page we're reading
datas DataService
- currBlock Block
- currConn DNConn
}
-func (f *Reader) ReadAt(p []byte, offset uint64, size uint32) (n int, err error) {
- nRead := uint32(0)
- for ; nRead < off ; {
- // make sure we're at right block
-
- // figure out page to read and read it
-
- // copy to dest and update
-
- }
-}
-// io.Reader
-func (f *Reader) Read(p []byte) (n int, err error) {
+func (f *Reader) ReadAt(p []byte, offset uint64, length uint32) (n uint32, err error) {
nRead := uint32(0)
- numToRead := uint32(len(p))
- numLeftInFile := f.inode.Length - f.globalPos
- if (numLeftInFile == 0) { return 0,io.EOF }
- // shorten read to "rest of file" if necessary
- if (numLeftInFile < uint64(numToRead)) {
- numToRead = uint32(numLeftInFile)
- }
- var innerN uint32
-
- for ; (nRead < numToRead) ;{
- // make sure buffer has bytes, read more if we need to
- if (f.bufferPos == uint32(len(f.buffer))) {
- err = f.refillReadBuffer()
- if (err != nil) { return int(nRead),err }
- }
+ // loop until done
+ for ; nRead < length ; {
+ // get conn to block
+ block,err := blockForPos(offset + uint64(nRead), f.inode)
- // copy from buffer to dest, up to PAGESIZE bytes
- innerN = uint32(numToRead - nRead)
- if (innerN > PAGESIZE) { innerN = PAGESIZE }
- for i := uint32(0) ; i < innerN ; i++ {
- p[i] = f.buffer[i]
+ if (err != nil) {
+ return nRead,err
}
- // end loop and repeat until done
- nRead += innerN
- f.globalPos += uint64(innerN)
- f.blockPos += uint32(innerN)
- f.bufferPos += innerN
+ // read
+ blockPos := offset - block.StartPos
+ numToReadFromBlock := uint32(block.EndPos - blockPos)
+ if (numToReadFromBlock > length) { numToReadFromBlock = length }
+ conn,err := f.datas.Read(block)
+ if (err != nil) { return nRead,err }
+ defer conn.Close()
+ err = conn.Read(uint32(blockPos),numToReadFromBlock,p)
+ if (err != nil) { return nRead,err }
+ nRead += numToReadFromBlock
}
- return int(nRead),nil
+ return nRead,nil
}
-func (f *Reader) refillReadBuffer() (err error) {
- // if we're at the end of the file, error
- if (f.globalPos == f.inode.Length) { return io.ErrUnexpectedEOF }
- // check if we need to move to the next block
- if (f.blockPos == BLOCKSIZE) {
- err := f.switchBlock(f.currBlock.NumInFile + 1)
- if (err != nil) { return err }
+func blockForPos(offset uint64, inode Inode) (blk Block, err error) {
+ if (offset >= inode.Length) {
+ return Block{}, errors.New(fmt.Sprintf("offset %d greater than block length %d", offset, inode.Length))
}
+ for i := 0 ; i < len(inode.Blocks) ; i++ {
+ blk := inode.Blocks[i]
+ if (offset > blk.StartPos && offset < blk.EndPos) {
+ return blk,nil
+ }
+ }
+ return Block{},errors.New(fmt.Sprintf("offset %d not found in any blocks for inode %d, bad file?", offset, inode.Inodeid))
- // read the buffer
- err = currConn.Read(currBlock.Inodeid,
- if (err != nil) { return err }
- return f.currSession.Read(f.buffer)
-}
-
-func (f *Reader) switchBlock(blockNum uint64) error {
- err := f.currSession.Close()
- if (err != nil) { return err }
- f.currSession,err = f.datas.OpenBlock(f.inode.Blocks[blockNum])
- return err // hopefully nil
}
-
//io.Closer
func (f *Reader) Close() error {
return nil
}
type Writer struct {
- path PathEntry
inode Inode
- buffer []byte
globalPos uint64 // pos in file
blockPos int // pos within block
bufferPos int // pos within buffer
View
66 fuseconnector.go
@@ -29,7 +29,8 @@ func (m mfile) Close() (err error) {
type MaggieFuse struct {
names NameService
datas DataService
- openFiles map[uint64] *mfile
+ openRFiles map[uint64] *Reader
+ openWFiles map[uint64] *Writer
fhCounter uint64
}
@@ -90,7 +91,7 @@ func (m *MaggieFuse) Lookup(out *raw.EntryOut, h *raw.InHeader, name string) (co
parent,err := m.names.GetInode(h.NodeId)
childId := parent.Children[name]
// Lookup PathEntry by name
- child := m.names.GetInode(childId)
+ child,err := m.names.GetInode(childId)
if err != nil {
return fuse.EROFS
}
@@ -111,8 +112,8 @@ func fillEntryOut(out *raw.EntryOut, i *Inode) {
out.Size = i.Length
out.Blocks = numBlocks(i.Length, PAGESIZE)
out.Atime = uint64(0) // always 0 for atime
- out.Mtime = i.Mtime // Mtime is user modifiable and is the last time data changed
- out.Ctime = i.Ctime // Ctime is tracked by the FS and changes when attrs or data change
+ out.Mtime = uint64(i.Mtime) // Mtime is user modifiable and is the last time data changed
+ out.Ctime = uint64(i.Ctime) // Ctime is tracked by the FS and changes when attrs or data change
out.Atimensec = uint32(0)
out.Mtimensec = uint32(0)
out.Ctimensec = uint32(0)
@@ -138,8 +139,8 @@ func (m *MaggieFuse) GetAttr(out *raw.AttrOut, header *raw.InHeader, input *raw.
out.Size = i.Length
out.Blocks = numBlocks(i.Length, PAGESIZE)
out.Atime = uint64(0) // always 0 for atime
- out.Mtime = i.Mtime // Mtime is user modifiable and is the last time data changed
- out.Ctime = i.Ctime // Ctime is tracked by the FS and changes when attrs or data change
+ out.Mtime = uint64(i.Mtime) // Mtime is user modifiable and is the last time data changed
+ out.Ctime = uint64(i.Ctime) // Ctime is tracked by the FS and changes when attrs or data change
out.Atimensec = uint32(0)
out.Mtimensec = uint32(0)
out.Ctimensec = uint32(0)
@@ -156,9 +157,15 @@ func (m *MaggieFuse) GetAttr(out *raw.AttrOut, header *raw.InHeader, input *raw.
}
func (m *MaggieFuse) Open(out *raw.OpenOut, header *raw.InHeader, input *raw.OpenIn) (status fuse.Status) {
+ // TODO handle open flags
+
+ // if read, readable = true
+
+ // if write, then
+ // if file length = 0, open fine
+ // if file length > 0, we must be either TRUNC or APPEND
// open flags
readable,writable := parseWRFlags(input.Flags)
- // TODO handle other open flags here
appnd := (input.Flags & syscall.O_APPEND != 0)
// get inode
@@ -170,25 +177,19 @@ func (m *MaggieFuse) Open(out *raw.OpenOut, header *raw.InHeader, input *raw.Ope
// allocate new filehandle
fh := atomic.AddUint64(&m.fhCounter,uint64(1))
- r := &Reader{}
- w := &Writer{}
+ var r *Reader
+ var w *Writer
if (readable) {
r,err = NewReader(inode,m.datas)
if (err != nil) { return fuse.EROFS }
+ m.openRFiles[fh] = r
}
if (writable) {
w,err = NewWriter(inode,m.datas)
if (err != nil) { return fuse.EROFS }
+ m.openWFiles[fh]
}
- file := mfile {
- r,
- w,
- writable,
- readable,
- fh,
- appnd} //append mode
- m.openFiles[fh] = &file
// output
out.Fh = fh
out.OpenFlags = raw.FOPEN_KEEP_CACHE
@@ -213,7 +214,7 @@ func parseWRFlags(flags uint32) (bool, bool) {
}
func (m *MaggieFuse) SetAttr(out *raw.AttrOut, header *raw.InHeader, input *raw.SetAttrIn) (code fuse.Status) {
- if (input.Valid & (FATTR_MODE | FATTR_UID | FATTR_GID | FATTR_MTIME | FATTR_MTIME_NOW) == 0) {
+ if (input.Valid & (raw.FATTR_MODE | raw.FATTR_UID | raw.FATTR_GID | raw.FATTR_MTIME | raw.FATTR_MTIME_NOW) == 0) {
// if none of the items we care about were modified, skip it
return fuse.OK
}
@@ -237,9 +238,8 @@ func (m *MaggieFuse) SetAttr(out *raw.AttrOut, header *raw.InHeader, input *raw.
err = m.names.SaveInode(inode)
if (err != nil) {
return fuse.EROFS
- } else {
- return fuse.OK
- }
+ }
+ return fuse.OK
}
func (m *MaggieFuse) Readlink(header *raw.InHeader) (out []byte, code fuse.Status) {
@@ -253,18 +253,21 @@ func (m *MaggieFuse) Mknod(out *raw.EntryOut, header *raw.InHeader, input *raw.M
//if err != nil {
//return fuse.EROFS
//}
- currTime := uint64(time.Now().Unix())
+ currTime := time.Now().Unix()
i := Inode{
0, // id 0 to start
- 0,
+ 0, // gen 0
FTYPE_REG,
0,
+ 0x777,
currTime,
currTime,
0,
header.Uid,
header.Gid,
- make([]Block,0,100) }
+ make([]Block,0,100),
+ map[string] uint64 {},
+ }
// save
id,err := m.names.AddInode(i)
@@ -279,21 +282,27 @@ func (m *MaggieFuse) Mknod(out *raw.EntryOut, header *raw.InHeader, input *raw.M
func (m *MaggieFuse) Mkdir(out *raw.EntryOut, header *raw.InHeader, input *raw.MkdirIn, name string) (code fuse.Status) {
// lookup parent
- parent := m.names.GetInode(header.NodeId)
+ parent,err := m.names.GetInode(header.NodeId)
+ if (err != nil) {
+ return fuse.EROFS
+ }
// make new child
- currTime := uint64(time.Now().Unix())
+ currTime := time.Now().Unix()
i := Inode{
0, // id 0 to start, we get id when inserting
0,
FTYPE_DIR,
0,
+ 0x777,
currTime,
currTime,
0,
header.Uid,
header.Gid,
- make([]Block,0,100) }
+ make([]Block,0,100),
+ map[string] uint64{},
+ }
// save
id,err := m.names.AddInode(i)
@@ -318,7 +327,8 @@ func (m *MaggieFuse) Mkdir(out *raw.EntryOut, header *raw.InHeader, input *raw.M
func (m *MaggieFuse) Unlink(header *raw.InHeader, name string) (code fuse.Status) {
// receive parent inode id and name
// pull parent
- parent := m.names.GetInode(header.NodeId)
+ parent,err := m.names.GetInode(header.NodeId)
+ if (err != nil) { return fuse.EROFS }
// look up node for name
// resolve full path
View
45 memnames.go
@@ -7,7 +7,6 @@ import (
// implements nameservice
type MemNames struct {
- paths map[string]PathEntry
nodes map[uint64]Inode
idCounter uint64
s sync.Mutex
@@ -17,22 +16,9 @@ func (m MemNames) Format() (err error) {
return nil
}
-func NewMemNames() (names NameService) {
- return MemNames{make(map[string]PathEntry),make(map[uint64]Inode),uint64(0),sync.Mutex{}}
-}
-
-func (n MemNames) GetPathInode(path string) (p PathEntry, i Inode, err error) {
- n.s.Lock()
- defer n.s.Unlock()
- return PathEntry{},Inode{},nil
-
-}
-
-func (n MemNames) GetPathEntry(path string) (p PathEntry, err error) {
- n.s.Lock()
- defer n.s.Unlock()
- return n.paths[path],nil
-}
+//func NewMemNames() (names NameService) {
+ //return MemNames{make(map[string]PathEntry),make(map[uint64]Inode),uint64(0),sync.Mutex{}}
+//}
func (n MemNames) GetInode(nodeid uint64) (i Inode, err error) {
n.s.Lock()
@@ -49,31 +35,6 @@ func (n MemNames) AddInode(node Inode) (id uint64, err error) {
return id,nil
}
-func (n MemNames) AddPathEntry(pe PathEntry) (err error) {
- n.s.Lock()
- defer n.s.Unlock()
- n.paths[pe.Path] = pe
- return nil
-}
-
-func (n MemNames) RenamePathEntry(oldPath string, newPath string) (err error) {
- n.s.Lock()
- defer n.s.Unlock()
- pe := n.paths[oldPath]
- delete(n.paths,oldPath)
- pe.Path = newPath
- n.paths[newPath] = pe
- return nil
-
-}
-
-func (n MemNames) LinkPathEntry(path string, nodeid uint64) (err error) {
- n.s.Lock()
- defer n.s.Unlock()
- //node Inode :=
- return nil
-}
-
func (n MemNames) StatFs() (stat syscall.Statfs_t, err error) {
n.s.Lock()
defer n.s.Unlock()
View
28 services.go
@@ -13,35 +13,39 @@ type NameService interface {
AddInode(node Inode) (id uint64, err error)
// updates existing inode
SaveInode(node Inode) (err error)
+ // acquires write lock
+ WriteLock(nodeid uint64) (lock WriteLock, err error)
// links an entry
Link(parent uint64, child uint64, name string)
// unlinks an entry
Unlink(parent uint64, name string)
+}
- // persists a PathEntry
- AddPathEntry(pe PathEntry) (err error)
- RenamePathEntry(oldPath string, newPath string) (err error)
- LinkPathEntry(path string, nodeid uint64) (err error)
- // todo attrs
+type WriteLock interface {
+ Unlock()
}
type DataService interface {
- GetConn(datanode string) (conn DNConn, err error)
+ Read(blk Block) (conn BlockReader, err error)
+
+ Write(blk Block) (conn BlockWriter, err error)
}
// represents a session of interacting with a block of a file
// each 16MB block consists of 4096 pages of 4096 bytes apiece
// sessions are navigated by seeking to a page number and then
// reading or writing full pages of 4096 bytes
-type DNConn interface {
+type BlockReader interface {
- // reads 1 page, will throw error of p is < 4096 bytes
- Read(blockid uint64, page uint64, p []byte) (err error)
+ // reads some bytes
+ Read(start uint32, length uint32, p []byte) (err error)
- // writes 1 page, will throw error if p is not exactly 4096 bytes
- // if file is not yet this long, we will throw error
- Write(blockid uint64, page uint64, p []byte) (err error)
// closes or returns to pool
Close() (err error)
}
+
+type BlockWriter interface {
+ Append(p []byte) (err error)
+ Close() (err error)
+}
View
19 types.go
@@ -6,23 +6,14 @@ const (
FTYPE_LNK = int(2)
)
-type PathEntry struct {
- Path string
- Inodeid uint64
- Ftype int
- SymlinkDest string
- Uid uint32
- Gid uint32
-}
-
type Inode struct {
Inodeid uint64
Generation uint64
Ftype int
Length uint64
Mode uint32
- Mtime uint64 // changed on data - can be changed by user with touch
- Ctime uint64 // changed on file attr change or date -- owned by kernel
+ Mtime int64 // changed on data - can be changed by user with touch
+ Ctime int64 // changed on file attr change or date -- owned by kernel
Nlink uint32 // number of paths linked to this inode
Uid uint32
Gid uint32
@@ -31,10 +22,8 @@ type Inode struct {
}
type Block struct {
- Inodeid uint64
- NumInFile uint64
- FirstPage uint64
- LastPage uint64
+ StartPos uint64
+ EndPos uint64
Locations []string
}

0 comments on commit a6a2558

Please sign in to comment.
Something went wrong with that request. Please try again.