Initial commit
Proof-of-concept implementation. Bugs will occur.
This commit is contained in:
133
vendor/github.com/hanwen/go-fuse/v2/fs/inode_children.go
generated
vendored
Normal file
133
vendor/github.com/hanwen/go-fuse/v2/fs/inode_children.go
generated
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright 2023 the Go-FUSE Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type childEntry struct {
|
||||
Name string
|
||||
Inode *Inode
|
||||
|
||||
// TODO: store int64 changeCounter of the parent, so we can
|
||||
// use the changeCounter as a directory offset.
|
||||
}
|
||||
|
||||
// inodeChildren is a hashmap with deterministic ordering. It is
|
||||
// important to return the children in a deterministic order for 2
|
||||
// reasons:
|
||||
//
|
||||
// 1. if the ordering is non-deterministic, multiple concurrent
|
||||
// readdirs can lead to cache corruption (see issue #391)
|
||||
//
|
||||
// 2. it simplifies the implementation of directory seeking: the NFS
|
||||
// protocol doesn't open and close directories. Instead, a directory
|
||||
// read must always be continued from a previously handed out offset.
|
||||
//
|
||||
// By storing the entries in insertion order, and marking them with a
|
||||
// int64 logical timestamp, the logical timestamp can serve as readdir
|
||||
// cookie.
|
||||
type inodeChildren struct {
|
||||
// index into children slice.
|
||||
childrenMap map[string]int
|
||||
children []childEntry
|
||||
}
|
||||
|
||||
func (c *inodeChildren) init() {
|
||||
c.childrenMap = make(map[string]int)
|
||||
}
|
||||
|
||||
func (c *inodeChildren) String() string {
|
||||
var ss []string
|
||||
for _, e := range c.children {
|
||||
ch := e.Inode
|
||||
ss = append(ss, fmt.Sprintf("%q=i%d[%s]", e.Name, ch.stableAttr.Ino, modeStr(ch.stableAttr.Mode)))
|
||||
}
|
||||
return strings.Join(ss, ",")
|
||||
}
|
||||
|
||||
func (c *inodeChildren) get(name string) *Inode {
|
||||
idx, ok := c.childrenMap[name]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return c.children[idx].Inode
|
||||
}
|
||||
|
||||
func (c *inodeChildren) compact() {
|
||||
nc := make([]childEntry, 0, 2*len(c.childrenMap)+1)
|
||||
nm := make(map[string]int, len(c.childrenMap))
|
||||
for _, e := range c.children {
|
||||
if e.Inode == nil {
|
||||
continue
|
||||
}
|
||||
nm[e.Name] = len(nc)
|
||||
nc = append(nc, e)
|
||||
}
|
||||
|
||||
c.childrenMap = nm
|
||||
c.children = nc
|
||||
}
|
||||
|
||||
func (c *inodeChildren) set(parent *Inode, name string, ch *Inode) {
|
||||
idx, ok := c.childrenMap[name]
|
||||
if !ok {
|
||||
if cap(c.children) == len(c.children) {
|
||||
c.compact()
|
||||
}
|
||||
|
||||
idx = len(c.children)
|
||||
c.children = append(c.children, childEntry{})
|
||||
}
|
||||
|
||||
c.childrenMap[name] = idx
|
||||
c.children[idx] = childEntry{Name: name, Inode: ch}
|
||||
parent.changeCounter++
|
||||
|
||||
ch.parents.add(parentData{name, parent})
|
||||
ch.changeCounter++
|
||||
}
|
||||
|
||||
func (c *inodeChildren) len() int {
|
||||
return len(c.childrenMap)
|
||||
}
|
||||
|
||||
func (c *inodeChildren) toMap() map[string]*Inode {
|
||||
r := make(map[string]*Inode, len(c.childrenMap))
|
||||
for _, e := range c.children {
|
||||
if e.Inode != nil {
|
||||
r[e.Name] = e.Inode
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (c *inodeChildren) del(parent *Inode, name string) {
|
||||
idx, ok := c.childrenMap[name]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
ch := c.children[idx].Inode
|
||||
|
||||
delete(c.childrenMap, name)
|
||||
c.children[idx] = childEntry{}
|
||||
ch.parents.delete(parentData{name, parent})
|
||||
ch.changeCounter++
|
||||
parent.changeCounter++
|
||||
}
|
||||
|
||||
func (c *inodeChildren) list() []childEntry {
|
||||
r := make([]childEntry, 0, len(c.childrenMap))
|
||||
for _, e := range c.children {
|
||||
if e.Inode != nil {
|
||||
r = append(r, e)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
Reference in New Issue
Block a user