Commit 1589f20c authored by Ivan Krasin's avatar Ivan Krasin

Added FileSystem.Lookup(parent, filename). It works. Also, I see that if I do...

Added FileSystem.Lookup(parent, filename). It works. Also, I see that if I do several ls, the program stucks
parent d2f2fd32
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"path"
) )
const ( const (
...@@ -13,6 +14,7 @@ const ( ...@@ -13,6 +14,7 @@ const (
) )
type FileSystem interface { type FileSystem interface {
Lookup(parent, filename string) (out *Attr, code Error, err os.Error)
GetAttr(h *InHeader, in *GetAttrIn) (out *AttrOut, code Error, err os.Error) GetAttr(h *InHeader, in *GetAttrIn) (out *AttrOut, code Error, err os.Error)
} }
...@@ -37,7 +39,7 @@ func loop(f *os.File, fs FileSystem, errors chan os.Error) { ...@@ -37,7 +39,7 @@ func loop(f *os.File, fs FileSystem, errors chan os.Error) {
defer close(toW) defer close(toW)
go writer(f, toW, errors) go writer(f, toW, errors)
managerReq := make(chan *managerRequest, 100) managerReq := make(chan *managerRequest, 100)
startManager(managerReq) startManager(fs, managerReq)
defer close(managerReq) defer close(managerReq)
for { for {
n, err := f.Read(buf) n, err := f.Read(buf)
...@@ -183,7 +185,7 @@ func openDir(h *InHeader, r io.Reader, mr chan *managerRequest) (data [][]byte, ...@@ -183,7 +185,7 @@ func openDir(h *InHeader, r io.Reader, mr chan *managerRequest) (data [][]byte,
return return
} }
fmt.Printf("FUSE_OPENDIR: %v\n", in) fmt.Printf("FUSE_OPENDIR: %v\n", in)
resp := makeManagerRequest(mr, h.NodeId, 0, openDirOp) resp := makeManagerRequest(mr, h.NodeId, 0, openDirOp, "")
err = resp.err err = resp.err
if err != nil { if err != nil {
data, err = serialize(h, EIO, nil) data, err = serialize(h, EIO, nil)
...@@ -204,7 +206,7 @@ func readDir(h *InHeader, r io.Reader, mr chan *managerRequest) (data [][]byte, ...@@ -204,7 +206,7 @@ func readDir(h *InHeader, r io.Reader, mr chan *managerRequest) (data [][]byte,
return return
} }
fmt.Printf("FUSE_READDIR: %v\n", in) fmt.Printf("FUSE_READDIR: %v\n", in)
resp := makeManagerRequest(mr, h.NodeId, in.Fh, getHandleOp) resp := makeManagerRequest(mr, h.NodeId, in.Fh, getHandleOp, "")
err = resp.err err = resp.err
if err != nil { if err != nil {
data, _ = serialize(h, EIO, nil) data, _ = serialize(h, EIO, nil)
...@@ -260,9 +262,18 @@ func readDir(h *InHeader, r io.Reader, mr chan *managerRequest) (data [][]byte, ...@@ -260,9 +262,18 @@ func readDir(h *InHeader, r io.Reader, mr chan *managerRequest) (data [][]byte,
func lookup(h *InHeader, r *bytes.Buffer, mr chan *managerRequest) (data [][]byte, err os.Error) { func lookup(h *InHeader, r *bytes.Buffer, mr chan *managerRequest) (data [][]byte, err os.Error) {
filename := string(r.Bytes()) filename := string(r.Bytes())
fmt.Printf("filename: %s\n", filename) fmt.Printf("filename: %s\n", filename)
resp := makeManagerRequest(mr, h.NodeId, 0, lookupOp, filename)
if resp.err != nil {
return serialize(h, EIO, nil)
}
if resp.code != OK {
return serialize(h, resp.code, nil)
}
out := new(EntryOut) out := new(EntryOut)
out.NodeId = h.NodeId + 1 out.NodeId = resp.nodeId
out.Mode = S_IFDIR out.Attr = *resp.attr
out.AttrValid = 60
out.EntryValid = 60
res := OK res := OK
data, err = serialize(h, res, out) data, err = serialize(h, res, out)
return return
...@@ -276,7 +287,7 @@ func releaseDir(h *InHeader, r io.Reader, mr chan *managerRequest) (data [][]byt ...@@ -276,7 +287,7 @@ func releaseDir(h *InHeader, r io.Reader, mr chan *managerRequest) (data [][]byt
return return
} }
fmt.Printf("FUSE_RELEASEDIR: %v\n", in) fmt.Printf("FUSE_RELEASEDIR: %v\n", in)
resp := makeManagerRequest(mr, h.NodeId, in.Fh, closeDirOp) resp := makeManagerRequest(mr, h.NodeId, in.Fh, closeDirOp, "")
err = resp.err err = resp.err
return return
} }
...@@ -301,6 +312,7 @@ const ( ...@@ -301,6 +312,7 @@ const (
openDirOp = FileOp(1) openDirOp = FileOp(1)
getHandleOp = FileOp(2) getHandleOp = FileOp(2)
closeDirOp = FileOp(3) closeDirOp = FileOp(3)
lookupOp = FileOp(4)
) )
type managerRequest struct { type managerRequest struct {
...@@ -308,12 +320,16 @@ type managerRequest struct { ...@@ -308,12 +320,16 @@ type managerRequest struct {
fh uint64 fh uint64
op FileOp op FileOp
resp chan *managerResponse resp chan *managerResponse
filename string
} }
type managerResponse struct { type managerResponse struct {
nodeId uint64
fh uint64 fh uint64
dirReq chan *dirRequest dirReq chan *dirRequest
err os.Error err os.Error
code Error
attr *Attr
} }
type dirEntry struct { type dirEntry struct {
...@@ -338,19 +354,29 @@ type dirHandle struct { ...@@ -338,19 +354,29 @@ type dirHandle struct {
} }
type manager struct { type manager struct {
fs FileSystem
dirHandles map[uint64]*dirHandle dirHandles map[uint64]*dirHandle
cnt uint64 cnt uint64
nodes map[uint64] string
nodesByPath map[string] uint64
nodeMax uint64
} }
func startManager(requests chan *managerRequest) { func startManager(fs FileSystem, requests chan *managerRequest) {
m := new(manager) m := new(manager)
m.fs = fs
m.dirHandles = make(map[uint64]*dirHandle) m.dirHandles = make(map[uint64]*dirHandle)
m.nodes = make(map[uint64]string)
m.nodes[1] = "" // Root
m.nodeMax = 1
m.nodesByPath = make(map[string]uint64)
m.nodesByPath[""] = 1
go m.run(requests) go m.run(requests)
} }
func makeManagerRequest(mr chan *managerRequest, nodeId uint64, fh uint64, op FileOp) (resp *managerResponse) { func makeManagerRequest(mr chan *managerRequest, nodeId uint64, fh uint64, op FileOp, filename string) (resp *managerResponse) {
fmt.Printf("makeManagerRequest, nodeId = %d, fh = %d, op = %d\n", nodeId, fh, op) fmt.Printf("makeManagerRequest, nodeId = %d, fh = %d, op = %d, filename = %s\n", nodeId, fh, op, filename)
req := &managerRequest{nodeId, fh, op, make(chan *managerResponse, 1)} req := &managerRequest{nodeId, fh, op, make(chan *managerResponse, 1), filename}
mr <- req mr <- req
resp = <-req.resp resp = <-req.resp
fmt.Printf("makeManagerRequest, resp: %v\n", resp) fmt.Printf("makeManagerRequest, resp: %v\n", resp)
...@@ -367,6 +393,8 @@ func (m *manager) run(requests chan *managerRequest) { ...@@ -367,6 +393,8 @@ func (m *manager) run(requests chan *managerRequest) {
resp = m.getHandle(req) resp = m.getHandle(req)
case closeDirOp: case closeDirOp:
resp = m.closeDir(req) resp = m.closeDir(req)
case lookupOp:
resp = m.lookup(req)
default: default:
resp := new(managerResponse) resp := new(managerResponse)
resp.err = os.NewError(fmt.Sprintf("Unknown FileOp: %v", req.op)) resp.err = os.NewError(fmt.Sprintf("Unknown FileOp: %v", req.op))
...@@ -413,6 +441,35 @@ func (m *manager) closeDir(req *managerRequest) (resp *managerResponse) { ...@@ -413,6 +441,35 @@ func (m *manager) closeDir(req *managerRequest) (resp *managerResponse) {
return return
} }
func (m *manager) lookup(req *managerRequest) (resp *managerResponse) {
resp = new(managerResponse)
parent, ok := m.nodes[req.nodeId]
if !ok {
resp.err = os.NewError(fmt.Sprintf("lookup: can't lookup parent node with id: %d", req.nodeId))
return
}
attr, code, err := m.fs.Lookup(parent, req.filename)
if err != nil {
resp.err = err
return
}
if code != OK {
resp.code = code
}
resp.attr = attr
fullPath := path.Clean(path.Join(parent, req.filename))
nodeId, ok := m.nodesByPath[fullPath]
if !ok {
m.nodeMax++
nodeId = m.nodeMax
m.nodes[nodeId] = fullPath
m.nodesByPath[fullPath] = nodeId
}
resp.nodeId = nodeId
return
}
func readDirRoutine(requests chan *dirRequest) { func readDirRoutine(requests chan *dirRequest) {
defer close(requests) defer close(requests)
entries := []*dirEntry{ entries := []*dirEntry{
......
package fuse package fuse
import ( import (
"fmt"
"log" "log"
"os" "os"
"path"
"testing" "testing"
"time"
) )
const ( const (
...@@ -19,6 +22,14 @@ func (fs *testFuse) GetAttr(h *InHeader, in *GetAttrIn) (out *AttrOut, code Erro ...@@ -19,6 +22,14 @@ func (fs *testFuse) GetAttr(h *InHeader, in *GetAttrIn) (out *AttrOut, code Erro
return return
} }
func (fs *testFuse) Lookup(parent, filename string) (out *Attr, code Error, err os.Error) {
fmt.Printf("testFuse.Lookup: %s\n", path.Join(parent, filename))
out = new(Attr)
out.Mode = S_IFDIR
out.Mtime = uint64(time.Seconds())
return
}
func errorHandler(errors chan os.Error) { func errorHandler(errors chan os.Error) {
for err := range errors { for err := range errors {
log.Stderr("MountPoint.errorHandler: ", err) log.Stderr("MountPoint.errorHandler: ", err)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment