-
Notifications
You must be signed in to change notification settings - Fork 6
/
fs_cache.go
219 lines (183 loc) · 6.37 KB
/
fs_cache.go
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
package fs
import (
"github.com/cyverse/go-irodsclient/irods/util"
)
// ClearCache clears all file system caches
func (fs *FileSystem) ClearCache() {
fs.cache.ClearACLsCache()
fs.cache.ClearMetadataCache()
fs.cache.ClearEntryCache()
fs.cache.ClearNegativeEntryCache()
fs.cache.ClearDirCache()
}
// AddCacheEventHandler adds cache event handler
func (fs *FileSystem) AddCacheEventHandler(handler FilesystemCacheEventHandler) string {
return fs.cacheEventHandlerMap.AddEventHandler(handler)
}
// RemoveCacheEventHandler removes cache event handler
func (fs *FileSystem) RemoveCacheEventHandler(handlerID string) {
fs.cacheEventHandlerMap.RemoveEventHandler(handlerID)
}
// invalidateCacheForRemoveInternal invalidates cache for removal of the given file/dir
func (fs *FileSystem) invalidateCacheForRemoveInternal(path string, recurse bool) {
var entry *Entry
if recurse {
entry = fs.cache.GetEntryCache(path)
}
fs.cache.RemoveEntryCache(path)
fs.cache.RemoveACLsCache(path)
fs.cache.RemoveMetadataCache(path)
if recurse && entry != nil {
if entry.Type == DirectoryEntry {
dirEntries := fs.cache.GetDirCache(path)
for _, dirEntry := range dirEntries {
// do it recursively
fs.invalidateCacheForRemoveInternal(dirEntry, recurse)
}
}
}
// remove dircache and dir acl cache even if it is a file or unknown, no harm.
fs.cache.RemoveDirCache(path)
}
// invalidateCacheForDirCreate invalidates cache for creation of the given dir
func (fs *FileSystem) invalidateCacheForDirCreate(path string) {
fs.cache.RemoveNegativeEntryCache(path)
// parent dir's entry also changes
fs.cache.RemoveParentDirCache(path)
// parent dir's dir entry also changes
parentPath := util.GetIRODSPathDirname(path)
parentDirEntries := fs.cache.GetDirCache(parentPath)
if parentDirEntries != nil {
parentDirEntries = append(parentDirEntries, path)
fs.cache.AddDirCache(parentPath, parentDirEntries)
}
// send event
fs.cacheEventHandlerMap.SendDirCreateEvent(path)
}
// invalidateCacheForFileUpdate invalidates cache for update on the given file
func (fs *FileSystem) invalidateCacheForFileUpdate(path string) {
fs.cache.RemoveNegativeEntryCache(path)
fs.cache.RemoveEntryCache(path)
// modification doesn't affect to parent dir's modified time
// send event
fs.cacheEventHandlerMap.SendFileUpdateEvent(path)
}
// invalidateCacheForDirRemove invalidates cache for removal of the given dir
func (fs *FileSystem) invalidateCacheForDirRemove(path string, recurse bool) {
var entry *Entry
if recurse {
entry = fs.cache.GetEntryCache(path)
}
// we need to expunge all negatie entry caches under irodsDestPath
// since all sub-directories/files are also moved
fs.cache.RemoveAllNegativeEntryCacheForPath(path)
fs.cache.AddNegativeEntryCache(path)
fs.cache.RemoveEntryCache(path)
fs.cache.RemoveMetadataCache(path)
if recurse && entry != nil {
if entry.Type == DirectoryEntry {
dirEntries := fs.cache.GetDirCache(path)
for _, dirEntry := range dirEntries {
// do it recursively
fs.invalidateCacheForRemoveInternal(dirEntry, recurse)
}
}
}
fs.cache.RemoveDirCache(path)
fs.cache.RemoveACLsCache(path)
// parent dir's entry also changes
fs.cache.RemoveParentDirCache(path)
// parent dir's dir entry also changes
parentPath := util.GetIRODSPathDirname(path)
parentDirEntries := fs.cache.GetDirCache(parentPath)
if parentDirEntries != nil {
newParentDirEntries := []string{}
for _, dirEntry := range parentDirEntries {
if dirEntry != path {
newParentDirEntries = append(newParentDirEntries, dirEntry)
}
}
fs.cache.AddDirCache(parentPath, newParentDirEntries)
}
// send event
fs.cacheEventHandlerMap.SendDirRemoveEvent(path)
}
// invalidateCacheForDirExtract invalidates cache for bundle extraction of the given dir
// this occurs when extracting bundle files
func (fs *FileSystem) invalidateCacheForDirExtract(path string) {
entry := fs.cache.GetEntryCache(path)
// we need to expunge all negatie entry caches under irodsDestPath
// since it also creates sub-directories/files
fs.cache.RemoveAllNegativeEntryCacheForPath(path)
fs.cache.RemoveEntryCache(path)
fs.cache.RemoveMetadataCache(path)
if entry != nil {
if entry.Type == DirectoryEntry {
dirEntries := fs.cache.GetDirCache(path)
for _, dirEntry := range dirEntries {
// do it recursively
fs.invalidateCacheForRemoveInternal(dirEntry, true)
}
}
}
fs.cache.RemoveDirCache(path)
fs.cache.RemoveACLsCache(path)
// parent dir's entry also changes
fs.cache.RemoveParentDirCache(path)
// parent dir's dir entry also changes
parentPath := util.GetIRODSPathDirname(path)
parentDirEntries := fs.cache.GetDirCache(parentPath)
if parentDirEntries != nil {
exist := false
for _, parentDirEntry := range parentDirEntries {
if parentDirEntry == path {
exist = true
break
}
}
if !exist {
parentDirEntries = append(parentDirEntries, path)
}
fs.cache.AddDirCache(parentPath, parentDirEntries)
}
// send event
fs.cacheEventHandlerMap.SendDirCreateEvent(path)
}
// invalidateCacheForFileCreate invalidates cache for creation of the given file
func (fs *FileSystem) invalidateCacheForFileCreate(path string) {
fs.cache.RemoveNegativeEntryCache(path)
// parent dir's entry also changes
fs.cache.RemoveParentDirCache(path)
// parent dir's dir entry also changes
parentPath := util.GetIRODSPathDirname(path)
parentDirEntries := fs.cache.GetDirCache(parentPath)
if parentDirEntries != nil {
parentDirEntries = append(parentDirEntries, path)
fs.cache.AddDirCache(parentPath, parentDirEntries)
}
// send event
fs.cacheEventHandlerMap.SendFileCreateEvent(path)
}
// invalidateCacheForFileRemove invalidates cache for removal of the given file
func (fs *FileSystem) invalidateCacheForFileRemove(path string) {
fs.cache.AddNegativeEntryCache(path)
fs.cache.RemoveEntryCache(path)
fs.cache.RemoveACLsCache(path)
fs.cache.RemoveMetadataCache(path)
// parent dir's entry also changes
fs.cache.RemoveParentDirCache(path)
// parent dir's dir entry also changes
parentPath := util.GetIRODSPathDirname(path)
parentDirEntries := fs.cache.GetDirCache(parentPath)
if parentDirEntries != nil {
newParentDirEntries := []string{}
for _, dirEntry := range parentDirEntries {
if dirEntry != path {
newParentDirEntries = append(newParentDirEntries, dirEntry)
}
}
fs.cache.AddDirCache(parentPath, newParentDirEntries)
}
// send event
fs.cacheEventHandlerMap.SendFileRemoveEvent(path)
}