forked from keybase/kbfs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pointertable.go
110 lines (95 loc) · 2.35 KB
/
pointertable.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
// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.
package dokan
import (
"sync"
)
/* Keep Go pointers while passing integers to the C heap.
*
* These tables should only be used through the functions
* defined in this file.
*/
var fsTableLock sync.Mutex
var fsTable = make([]fsTableEntry, 0, 2)
var fiTableLock sync.Mutex
var fiTable = map[uint32]File{}
var fiIdx uint32
type fsTableEntry struct {
fs FileSystem
errChan chan error
fileCount uint32
}
func fsTableStore(fs FileSystem, ec chan error) uint32 {
fsTableLock.Lock()
defer fsTableLock.Unlock()
for i, c := range fsTable {
if c.fs == nil {
fsTable[i] = fsTableEntry{fs: fs, errChan: ec}
return uint32(i)
}
}
fsTable = append(fsTable, fsTableEntry{fs: fs, errChan: ec})
return uint32(len(fsTable) - 1)
}
func fsTableFree(slot uint32) {
fsTableLock.Lock()
defer fsTableLock.Unlock()
if int(slot) < len(fsTable) {
fsTable[slot] = fsTableEntry{}
}
}
func fsTableGet(slot uint32) FileSystem {
fsTableLock.Lock()
defer fsTableLock.Unlock()
return fsTable[slot].fs
}
func fsTableGetErrChan(slot uint32) chan error {
fsTableLock.Lock()
defer fsTableLock.Unlock()
return fsTable[slot].errChan
}
func fsTableGetFileCount(slot uint32) uint32 {
fsTableLock.Lock()
defer fsTableLock.Unlock()
return fsTable[slot].fileCount
}
func fiTableStoreFile(global uint32, fi File) uint32 {
fsTableLock.Lock()
fsTable[global].fileCount++
fsTableLock.Unlock()
fiTableLock.Lock()
defer fiTableLock.Unlock()
for {
// Just use a simple counter (inside the lock)
// to look for potential free file handles.
// Overflowing the counter is ok, but skip
// counter value zero (for better error detection).
fiIdx++
if fiIdx == 0 {
fiIdx++
}
_, exist := fiTable[fiIdx]
if !exist {
debug("FID alloc", fiIdx, fi)
fiTable[fiIdx] = fi
return fiIdx
}
}
}
func fiTableGetFile(file uint32) File {
fiTableLock.Lock()
var fi = fiTable[file]
fiTableLock.Unlock()
debug("FID get", file, fi)
return fi
}
func fiTableFreeFile(global uint32, file uint32) {
fsTableLock.Lock()
fsTable[global].fileCount--
fsTableLock.Unlock()
fiTableLock.Lock()
defer fiTableLock.Unlock()
debug("FID free", global, file, "=>", fiTable[file], "# of open files:", len(fiTable)-1)
delete(fiTable, file)
}