-
Notifications
You must be signed in to change notification settings - Fork 196
/
handle_map.go
213 lines (179 loc) · 6.08 KB
/
handle_map.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
/*
_____ _____ _____ ____ ______ _____ ------
| | | | | | | | | | | | |
| | | | | | | | | | | | |
| --- | | | | |-----| |---- | | |-----| |----- ------
| | | | | | | | | | | | |
| ____| |_____ | ____| | ____| | |_____| _____| |_____ |_____
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright © 2020-2024 Microsoft Corporation. All rights reserved.
Author : <blobfusedev@microsoft.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
*/
package handlemap
import (
"container/list"
"os"
"sync"
"time"
"github.com/Azure/azure-storage-fuse/v2/common"
"github.com/Azure/azure-storage-fuse/v2/common/cache_policy"
"go.uber.org/atomic"
)
type HandleID uint64
const InvalidHandleID HandleID = 0
// Flags represented in BitMap for various flags in the handle
const (
HandleFlagUnknown uint16 = iota
HandleFlagDirty // File has been modified with write operation or is a new file
HandleFlagFSynced // User has called fsync on the file explicitly
HandleFlagCached // File is cached in the local system by blobfuse2
)
// Structure to hold in memory cache for streaming layer
type Cache struct {
sync.RWMutex
*cache_policy.LRUCache
*common.BlockOffsetList
StreamOnly bool
HandleCount int64
}
type Buffers struct {
Cooked *list.List
Cooking *list.List
}
type Handle struct {
sync.RWMutex
FObj *os.File // File object being represented by this handle
CacheObj *Cache // Streaming layer cache for this handle
Buffers *Buffers
ID HandleID // Blobfuse assigned unique ID to this handle
Size int64 // Size of the file being handled here
Mtime time.Time
UnixFD uint64 // Unix FD created by create/open syscall
OptCnt uint64 // Number of operations done on this file
Flags common.BitMap16 // Various states of the file
Path string // Always holds path relative to mount dir
values map[string]interface{} // Map to hold other info if application wants to store
}
func NewHandle(path string) *Handle {
return &Handle{
ID: InvalidHandleID,
Path: path,
Size: 0,
Flags: 0,
OptCnt: 0,
values: make(map[string]interface{}),
CacheObj: nil,
FObj: nil,
Buffers: nil,
}
}
// Dirty : Handle is dirty or not
func (handle *Handle) Dirty() bool {
return handle.Flags.IsSet(HandleFlagDirty)
}
// Fsynced : Handle is Fsynced or not
func (handle *Handle) Fsynced() bool {
return handle.Flags.IsSet(HandleFlagFSynced)
}
// Cached : File is cached on local disk or not
func (handle *Handle) Cached() bool {
return handle.Flags.IsSet(HandleFlagCached)
}
// GetFileObject : Get the OS.File handle stored within
func (handle *Handle) GetFileObject() *os.File {
return handle.FObj
}
// SetFileObject : Store the OS.File handle
func (handle *Handle) SetFileObject(f *os.File) {
handle.FObj = f
}
// FD : Get Unix file descriptor
func (handle *Handle) FD() int {
return int(handle.UnixFD)
}
// SetValue : Store user defined parameter inside handle
func (handle *Handle) SetValue(key string, value interface{}) {
handle.values[key] = value
}
// GetValue : Retrieve user defined parameter from handle
func (handle *Handle) GetValue(key string) (interface{}, bool) {
val, ok := handle.values[key]
return val, ok
}
// GetValue : Retrieve user defined parameter from handle
func (handle *Handle) RemoveValue(key string) (interface{}, bool) {
val, ok := handle.values[key]
delete(handle.values, key)
return val, ok
}
// Cleanup : Delete all user defined parameter from handle
func (handle *Handle) Cleanup() {
for key := range handle.values {
delete(handle.values, key)
}
}
// defaultHandleMap holds a synchronized map[ HandleID ]*Handle
var defaultHandleMap sync.Map
var nextHandleID = *atomic.NewUint64(uint64(0))
// Add : Add the newly created handle to map and allocate a handle id
func Add(handle *Handle) HandleID {
var ok = true
var key HandleID
for ok {
key = HandleID(nextHandleID.Inc())
_, ok = defaultHandleMap.LoadOrStore(key, handle)
}
handle.ID = key
return key
}
// Delete : Remove handle object from map
func Delete(key HandleID) {
defaultHandleMap.Delete(key)
}
func CreateCacheObject(capacity int64, handle *Handle) {
handle.CacheObj = &Cache{
sync.RWMutex{},
cache_policy.NewLRUCache(capacity),
&common.BlockOffsetList{},
false,
0,
}
}
// GetHandles : Get map of handles stored
func GetHandles() *sync.Map {
return &defaultHandleMap
}
// Load : Search the handle object based on its id
func Load(key HandleID) (*Handle, bool) {
handleIF, ok := defaultHandleMap.Load(key)
if !ok {
return nil, false
}
handle := handleIF.(*Handle)
return handle, true
}
// Store function must not be used in production application.
// This is a utility function present only for test scenarios.
func Store(key HandleID, path string, _ uintptr) *Handle {
handle := &Handle{
ID: key,
Path: path,
}
defaultHandleMap.Store(key, handle)
return handle
}