作者:seacoastbo
项目:fus
// Returns nil for invalid handles.
func (c *serveConn) getHandle(id fuse.HandleID) (shandle *serveHandle) {
c.meta.Lock()
defer c.meta.Unlock()
if id < fuse.HandleID(len(c.handle)) {
shandle = c.handle[uint(id)]
}
if shandle == nil {
c.debug(missingHandle{
Handle: id,
MaxHandle: fuse.HandleID(len(c.handle)),
})
}
return
}
作者:hatchlin
项目:fuse_gdriv
// Allocate a file handle, held by the kernel until Release
func (sc *serveConn) open(req *fuse.OpenRequest) {
// This will be cheap, Lookup always preceeds Open, so the cache is warm
f, err := sc.db.FileByInode(uint64(req.Header.Node))
if err != nil {
req.RespondError(fuse.ENOENT)
return
}
var hId uint64
if !req.Flags.IsReadOnly() { // write access requested
if *readOnly {
// TODO: if allow_other, require uid == invoking uid to allow writes
req.RespondError(fuse.EPERM)
return
}
r, w := io.Pipe() // plumbing between WriteRequest and Drive
go sc.updateInDrive(f.File, r)
hId = sc.allocHandle(req.Header.Node, w)
} else {
hId = sc.allocHandle(req.Header.Node, nil)
}
resp := fuse.OpenResponse{Handle: fuse.HandleID(hId)}
fuse.Debug(fmt.Sprintf("Open Response: %+v", resp))
req.Respond(&resp)
}
作者:ttaco
项目:cluef
func handleIDGenerator() <-chan fuse.HandleID {
outChan := make(chan fuse.HandleID)
go func() {
for nextId := fuse.HandleID(1); ; nextId++ {
outChan <- nextId
}
}()
return outChan
}
作者:rsrsp
项目:fus
// Returns nil for invalid handles.
func (c *serveConn) getHandle(id fuse.HandleID) (shandle *serveHandle) {
c.meta.Lock()
defer c.meta.Unlock()
if id < fuse.HandleID(len(c.handle)) {
shandle = c.handle[uint(id)]
}
if shandle == nil {
println("missing handle", id, len(c.handle), shandle)
}
return
}
作者:seacoastbo
项目:fus
func (c *serveConn) saveHandle(handle Handle, nodeID fuse.NodeID) (id fuse.HandleID) {
c.meta.Lock()
shandle := &serveHandle{handle: handle, nodeID: nodeID}
if n := len(c.freeHandle); n > 0 {
id = c.freeHandle[n-1]
c.freeHandle = c.freeHandle[:n-1]
c.handle[id] = shandle
} else {
id = fuse.HandleID(len(c.handle))
c.handle = append(c.handle, shandle)
}
c.meta.Unlock()
return
}
作者:rsrsp
项目:fus
func (c *serveConn) saveHandle(handle Handle, nodeID fuse.NodeID) (id fuse.HandleID, shandle *serveHandle) {
c.meta.Lock()
shandle = &serveHandle{handle: handle, nodeID: nodeID}
if n := len(c.freeHandle); n > 0 {
id = c.freeHandle[n-1]
c.freeHandle = c.freeHandle[:n-1]
c.handle[id] = shandle
} else {
id = fuse.HandleID(len(c.handle))
c.handle = append(c.handle, shandle)
}
// Update mapping from node ID -> set of open Handle IDs.
for len(c.nodeHandles) <= int(nodeID) {
c.nodeHandles = append(c.nodeHandles, nil)
}
if c.nodeHandles[nodeID] == nil {
c.nodeHandles[nodeID] = make(map[fuse.HandleID]bool)
}
c.nodeHandles[nodeID][id] = true
c.meta.Unlock()
return
}
作者:hatchlin
项目:fuse_gdriv
// Create file in drive, allocate kernel filehandle for writes
func (sc *serveConn) create(req *fuse.CreateRequest) {
if *readOnly && !req.Flags.IsReadOnly() {
req.RespondError(fuse.EPERM)
return
}
pInode := uint64(req.Header.Node)
parent, err := sc.db.FileByInode(pInode)
if err != nil {
debug.Printf("failed to get parent file: %v", err)
req.RespondError(fuse.EIO)
return
}
p := &drive.ParentReference{Id: parent.Id}
f := &drive.File{Title: req.Name}
f.Parents = []*drive.ParentReference{p}
f, err = sc.service.Files.Insert(f).Do()
if err != nil {
debug.Printf("Files.Insert(f).Do(): %v", err)
req.RespondError(fuse.EIO)
return
}
inode, err := sc.db.InodeForFileId(f.Id)
if err != nil {
debug.Printf("failed creating inode for %v: %v", req.Name, err)
req.RespondError(fuse.EIO)
return
}
r, w := io.Pipe() // plumbing between WriteRequest and Drive
h := sc.allocHandle(fuse.NodeID(inode), w)
go sc.updateInDrive(f, r)
// Tell fuse and the OS about the file
df, err := sc.db.UpdateFile(nil, f)
if err != nil {
debug.Printf("failed to update levelDB for %v: %v", f.Id, err)
// The write has happened to drive, but we failed to update the kernel.
// The Changes API will update Fuse, and when the kernel metadata for
// the parent directory expires, the new file will become visible.
req.RespondError(fuse.EIO)
return
}
resp := fuse.CreateResponse{
// describes the opened handle
OpenResponse: fuse.OpenResponse{
Handle: fuse.HandleID(h),
Flags: fuse.OpenNonSeekable,
},
// describes the created file
LookupResponse: fuse.LookupResponse{
Node: fuse.NodeID(inode),
EntryValid: *driveMetadataLatency,
Attr: sc.attrFromFile(*df),
},
}
fuse.Debug(fmt.Sprintf("Create(%v in %v): %+v", req.Name, parent.Title, resp))
req.Respond(&resp)
}