Repository navigation
Expand file tree
/
Copy pathinode_cache.go
More file actions
110 lines (104 loc) · 2.5 KB
/
Copy pathinode_cache.go
File metadata and controls
110 lines (104 loc) · 2.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package fastsync
import (
"fmt"
"path/filepath"
)
func (c *Client) openInodeSpill() error {
parent, err := DirectoryPathNoFollow(c.InodeSpillDirectory)
if err != nil {
return err
}
dest, err := DirectoryPathNoFollow(c.BasePath)
if err != nil {
return err
}
rel, err := filepath.Rel(dest, parent)
if err != nil || rel == "." || filepath.IsLocal(rel) {
return fmt.Errorf("inode spill directory must be outside the destination tree")
}
store, err := openInodeStore(parent)
if err == nil {
c.inodesMu.Lock()
c.inodeStore = store
c.inodesMu.Unlock()
}
return err
}
func (c *Client) inodePathLocked(key inodeKey) (string, error) {
if entry := c.inodes[key]; entry != nil {
return entry.localhardlinkpath, nil
}
if c.inodeStore == nil {
return "", nil
}
return c.inodeStore.canonicalPath(key)
}
func (c *Client) admitInode(remote FileInfo) (*inodeinfo, bool, error) {
c.inodesMu.Lock()
defer c.inodesMu.Unlock()
key := inodeKey{remote.Dev, remote.Inode}
entry := c.inodes[key]
if entry == nil && c.inodeStore != nil {
var err error
entry, err = c.inodeStore.load(key)
if err != nil {
return nil, false, err
}
if entry != nil {
c.residentDisk++
c.inodes[key] = entry
}
}
follower := entry != nil
if entry == nil {
entry = &inodeinfo{localhardlinkpath: filepath.Join(c.BasePath, remote.Name), done: make(chan struct{}), remaining: remote.Nlink}
c.inodes[key] = entry
}
if entry.idle != nil {
c.inodeIdle.Remove(entry.idle)
entry.idle = nil
}
entry.users++
return entry, follower, nil
}
func (c *Client) releaseInode(remote FileInfo, entry *inodeinfo) error {
c.inodesMu.Lock()
defer c.inodesMu.Unlock()
key := inodeKey{remote.Dev, remote.Inode}
entry.users--
entry.remaining--
if entry.remaining == 0 {
if entry.diskBacked {
if err := c.inodeStore.remove(key); err != nil {
return err
}
c.residentDisk--
}
delete(c.inodes, key)
return nil
}
return c.idleInodeLocked(key, entry)
}
func (c *Client) idleInodeLocked(key inodeKey, entry *inodeinfo) error {
if c.inodeStore == nil || entry.users != 0 {
return nil
}
if entry.idle == nil {
entry.idle = c.inodeIdle.PushBack(key)
}
for len(c.inodes) > c.InodeMemoryGroups && c.inodeIdle.Len() > 0 {
oldest := c.inodeIdle.Front()
key := oldest.Value.(inodeKey)
entry := c.inodes[key]
if err := c.inodeStore.put(key, entry); err != nil {
return err
}
if entry.diskBacked {
c.residentDisk--
}
c.inodeIdle.Remove(oldest)
entry.idle = nil
delete(c.inodes, key)
}
return nil
}